使用交叉应用将列转置为行
transpose columns to row using cross apply
源数据
+--------+-------+---------------+------------+--------+--------------+-------+
| 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,原因?
您可以使用 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 |
+-------+---------------+-------+---------+---------------+----------+
假设你可以link RowNum + 1
上的"From"记录
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)
AND a1.Name != a2.Name
) 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
对 db<>fiddle here
的测试
源数据
+--------+-------+---------------+------------+--------+--------------+-------+
| 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,原因?
您可以使用 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 |
+-------+---------------+-------+---------+---------------+----------+
假设你可以link RowNum + 1
上的"From"记录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)
AND a1.Name != a2.Name
) 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
对 db<>fiddle here
的测试