Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вычисления на XQuery из поля XML  [new]
Alexey I.G.
Member

Откуда:
Сообщений: 18
Всем, доброго вечера.
Подскажите, пожалуйста, есть xml такого типа:
+

<a>
<historyValue>6</historyValue>
<historyDate>20140831000000</historyDate>
</a>
<a>
<historyValue>6</historyValue>
<historyDate>20140330000000</historyDate>
</a>
<a>
<historyValue>6</historyValue>
<historyDate>20130728000000</historyDate>
</a>
<a>
<historyValue>5</historyValue>
<historyDate>20130630000000</historyDate>
</a>
<a>
<historyValue>4</historyValue>
<historyDate>20130512000000</historyDate>
</a>
<a>
<historyValue>3</historyValue>
<historyDate>20130505000000</historyDate>
</a>
<a>
<historyValue>3</historyValue>
<historyDate>20130414000000</historyDate>
</a>
<a>
<historyValue>2</historyValue>
<historyDate>20130331000000</historyDate>
</a>
<a>
<historyValue>2</historyValue>
<historyDate>20130317000000</historyDate>
</a>
<a>
<historyValue>1</historyValue>
<historyDate>20130303000000</historyDate>
</a>
<a>
<historyValue>1</historyValue>
<historyDate>20130210000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20130203000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20130113000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20130106000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121230000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20121216000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121209000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121104000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121020000000</historyDate>
</a>

Как эти данные из него схлопнуть в одну строку вида 6XXXX6XXXXXXX654321A00.
Для формирования этой строки:
1. надо задать 2 параметра - дату начала и дату окончания
2. надо брать одно последнее значение по году и месяцу, т.е. из
+

<a>
<historyValue>0</historyValue>
<historyDate>20121230000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20121216000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121209000000</historyDate>
</a>

надо взять значение 0 на дату 20121230, остальные два отбросить
3. Если между historyDate есть пропуски в годах месяцах, то надо писать X
4. Посчитать кол-во "6","5","4" и т.д. в отдельных столбцах

С xml особо не работал, поискал в интернет - вроде нашел что можно сделать это все через FLWOR функции, только не могу понять с какой стороны пока подойти. Также не понятно как на языке XQuery преобразовать строку в дату из моих данных.

На языке T-SQL я это все реализовал, но не устраивает время работы.
Хочу попробовать теперь через XQuery, возможно получится быстрее.


Буду признателен за любые советы и рекомендации.
23 фев 15, 21:05    [17302551]     Ответить | Цитировать Сообщить модератору
 Re: Вычисления на XQuery из поля XML  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
Например так:
+
declare @x xml = N'<a>
<historyValue>6</historyValue>
<historyDate>20140831000000</historyDate>
</a>
<a>
<historyValue>6</historyValue>
<historyDate>20140330000000</historyDate>
</a>
<a>
<historyValue>6</historyValue>
<historyDate>20130728000000</historyDate>
</a>
<a>
<historyValue>5</historyValue>
<historyDate>20130630000000</historyDate>
</a>
<a>
<historyValue>4</historyValue>
<historyDate>20130512000000</historyDate>
</a>
<a>
<historyValue>3</historyValue>
<historyDate>20130505000000</historyDate>
</a>
<a>
<historyValue>3</historyValue>
<historyDate>20130414000000</historyDate>
</a>
<a>
<historyValue>2</historyValue>
<historyDate>20130331000000</historyDate>
</a>
<a>
<historyValue>2</historyValue>
<historyDate>20130317000000</historyDate>
</a>
<a>
<historyValue>1</historyValue>
<historyDate>20130303000000</historyDate>
</a>
<a>
<historyValue>1</historyValue>
<historyDate>20130210000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20130203000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20130113000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20130106000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121230000000</historyDate>
</a>
<a>
<historyValue>A</historyValue>
<historyDate>20121216000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121209000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121104000000</historyDate>
</a>
<a>
<historyValue>0</historyValue>
<historyDate>20121020000000</historyDate>
</a>';

declare @s date = '20121001', @e date = '20140901', @r varchar(max);

with c as
(
 select @s as d, left(convert(varchar(10), @s, 112), 6) as ym
 union all
 select
  dateadd(month, 1, c.d), left(convert(varchar(10), dateadd(month, 1, c.d), 112), 6)
 from
  c
 where
  dateadd(month, 1, c.d) < @e
),
x as
(
 select
  a.v, a.d, left(a.d, 6) as ym,
  row_number() over (partition by left(a.d, 6) order by a.d desc) as rn
 from
  @x.nodes('a') t(n) cross apply
  (select t.n.value('historyValue[1]', 'char(1)'), left(t.n.value('historyDate[1]', 'varchar(30)'), 8)) a(v, d)
)
select @r = (
 select
  isnull(x.v, 'X')
 from
  c left join
  x on x.ym = c.ym and x.rn = 1
 order by
  c.ym desc
 for xml path(''), type
).value('.', 'varchar(max)');

select @r;

Если задача не разовая - завести таблицу-календарь и пользоваться ей вместо первого CTE.
23 фев 15, 22:02    [17302714]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить