транспонировать столбцы в строку с помощью перекрестного применения - PullRequest
2 голосов
/ 11 марта 2019

Ori Data

+--------+-------+---------------+------------+--------+--------------+-------+
| RowNum | SeqNo |     Name      | NameReason | Gender | GenderReason |  ID   |
+--------+-------+---------------+------------+--------+--------------+-------+
|      1 | A123  | IronMan       |            | P      |              | E8888 |
|      2 | A123  | CaptainMarvel | A          | L      | A            | E8888 |
|      3 | A123  | Yoooo         |            |        |              | E8888 |
|      4 | A123  | Heyyy         |            |        |              | E8888 |
|      1 | B456  | Hey           |            |        |              | D2222 |
|      2 | B456  | DOTS          | A          |        |              | D2222 |
|      1 | C1234 | Hulk          |            |        |              | E8989 |
|      2 | C1234 | Cap           |            |        |              | E8989 |
|      3 | C1234 | Hat           |            |        |              | E8989 |
+--------+-------+---------------+------------+--------+--------------+-------+

Результат, который я хочу

+-------+-------+---------+---------------+----------+--------+
| SeqNo |  ID   | ColName |  From_Value   | To_Value | Reason |
+-------+-------+---------+---------------+----------+--------+
| A123  | E8888 | Name    | CaptainMarvel | IronMan  | A      |
| A123  | E8888 | Gender  | L             | P        | A      |
| B456  | D2222 | Name    | DOTS          | Hey      | A      |
| C1234 | E8989 | Name    | Cap           | Hulk     |        |
+-------+-------+---------+---------------+----------+--------+

Запрос:

select a.rownum, a.seqno, a.name, a.id,
       b.*
from #A a cross apply
( values ('Name', NameReason)
         ('Gender', GenderReason)
    ) b (colname, Reason)
where reason is not null

Примечание: хотите найти изменения. RowNum = 1 - это последнее обновление (To_Value), RowNum = 2 (From_Value). Rownum уже фильтрует верхний обновленный результат (rownumber () over (partitition). Мне просто нужно rownum = 2 (from_Value), rownum = 1 (to_value), которые другие игнорируют, , потому что 1 приложение может обновлять 100 раз, я просто нужно найти последние изменения сделаю.

Из запроса выше, как я могу изменить результат, который я хочу? Как я могу добавить from_value и to_value, причина?

Я имею дело с 10 миллионами + записями, более 20 столбцами, поэтому не могу жестко закодировать его.

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Предполагая, что вы можете связать запись "От" в RowNum + 1

SELECT q.SeqNo, q.ToName AS Name, q.ID, ca.ColName, ca.From_Value, ca.To_Value 
FROM
(
  SELECT 
   a1.ID, a1.SeqNo, a1.NameReason, a1.GenderReason, a1.RowNum, 
   a2.Name as FromName, a1.Name as ToName,
   a2.Gender AS FromGender, a1.Gender AS ToGender
  FROM #A a1
  JOIN #A a2 ON (a2.ID = a1.ID AND a2.RowNum = a1.RowNum + 1)
  WHERE (a1.NameReason IS NOT NULL OR a1.GenderReason IS NOT NULL)
) q
CROSS APPLY (VALUES 
 (1, 'Name', NameReason, FromName, ToName), 
 (2, 'Gender', GenderReason, FromGender, ToGender)
) ca (ColSeq, ColName, Reason, From_Value, To_Value)
WHERE ca.Reason IS NOT NULL
ORDER BY q.SeqNo, ca.ColSeq;

Но на основании комментариев имеет значение только RowNum 1 & 2.
Тогда это можно упростить.

SELECT q.SeqNo, q.ToName AS Name, q.ID, ca.ColName, ca.From_Value, ca.To_Value 
FROM
(
  SELECT 
   a1.ID, a1.SeqNo, 
   a1.NameReason, a2.Name as FromName, a1.Name as ToName,
   a1.GenderReason, a2.Gender AS FromGender, a1.Gender AS ToGender
  FROM #A a1
  JOIN #A a2 ON (a2.ID = a1.ID AND a2.RowNum = 2)
  WHERE a1.RowNum = 1
) q
CROSS APPLY (VALUES 
 (1, 'Name', NameReason, FromName, ToName), 
 (2, 'Gender', GenderReason, FromGender, ToGender)
) ca (ColSeq, ColName, Reason, From_Value, To_Value)
WHERE ca.Reason IS NOT NULL
ORDER BY q.SeqNo, ca.ColSeq;

Результат:

SeqNo Name    ID    ColName From_Value    To_Value
----- ------- ----- ------- ------------- --------
A123  IronMan E8888 Name    CaptainMarvel IronMan
A123  IronMan E8888 Gender  L             P
B456  Hey     D2222 Name    DOTS          Hey

Тест по дБ <> скрипка здесь

0 голосов
/ 11 марта 2019

Вы можете написать свой запрос следующим образом, используя UNION.

  select t1.SeqNo, 
       t1.Name, 
       t1.ID, 
       'Name'                  as ColName, 
       (select name 
        from   mytable mt 
        where  mt.SeqNo = t1.seqNo 
               and RowNum = 2) as From_Value, 
       t1.Name                 as To_Value 
from   mytable t1 
where  t1.RowNum = 1 
union all
select * 
from   (select t1.SeqNo, 
               t1.Name, 
               t1.ID, 
               'Gender'                as ColName, 
               t1.Gender               as From_Value, 
               (select Gender 
                from   mytable mt 
                where  mt.SeqNo = t1.seqNo 
                       and RowNum = 1) as To_Value 
        from   mytable t1 
        where  t1.RowNum = 2) t 
where  From_Value is not null 

Демонстрационная версия

Выход

+-------+---------------+-------+---------+---------------+----------+
| SeqNo | Name          | ID    | ColName | From_Value    | To_Value |
+-------+---------------+-------+---------+---------------+----------+
| A123  | CaptainMarvel | E8888 | Gender  | L             | P       |
+-------+---------------+-------+---------+---------------+----------+
| A123  | IronMan       | E8888 | Name    | CaptainMarvel | IronMan  |
+-------+---------------+-------+---------+---------------+----------+
| B456  | Hey           | D2222 | Name    | DOTS          | Hey      |
+-------+---------------+-------+---------+---------------+----------+
...