我有两个数据表
TAB1
-------------------------
| ID1 | ID2 | A | B |
| 1 | 8 |'John' | 9 |
| 2 | 9 |'Smith'| 0 |
TAB2
------------------------------------------
| NAME | ID1 | ID2 | VSTRING | VINT |ROOT|
| 'C1' | 1 | 8 | 'R01' | NULL | 'A'|
| 'C1' | 1 | 8 | 'R02' | NULL | 'B'|
| 'C2' | 1 | 8 | NULL | 9991 | 'B'|
| 'C1' | 2 | 9 | 'D02' | NULL | 'B'|
我需要一个会产生
的查询TAB3
-------------------------------------
| ID1 | ID2 | A | C1 | C2 |
| 1 | 8 | 'John' | 'R01' | 9991 |
| 2 | 9 | 'Smith'| 'D02' | NULL |
TAB1包含用户和ID。 TAB2包含动态结构中的列和值。如果一个单元格(参见[TAB2.NAME ='C1'和TAB2.ID1 = 1])具有多个值,则应采用与ROOT ='A'关联的值。
我唯一的问题是如何在ROOT列上获取正确的值。以下代码返回TAB3的正确结构,但值不正确。
select t.id1, t.id2, t.a,
max(case when t2.name = 'C2' then t2.vint end) c2,
max(case when t2.name = 'C1' then t2.vstring end) c1
from tab1 t
left join tab2 t2 on t.id1 = t2.id1 and t.id2 = t2.id2
group by t.id1, t.id2, t.a
理想情况下,我希望只有一个没有子查询的查询。
我设法通过子查询来解决这个问题,但解决方案太慢了。以上示例是Pivot on joined tables SQL Server的后续行动。 (PS:真实模型有近100个动态列)
答案 0 :(得分:0)
对于tab2
的每个组合,您似乎只想要一行name, id1
。 row_number()
功能可以为您完成此操作。它为每个这样的组分配一个序列。对于您的查询,此序列从root = 'A'
所在的行(如果有)开始。
完整查询与您的类似,但tab2
替换为子查询,on
条件略有修改:
select t.id1, t.id2, t.a,
max(case when t2.name = 'C2' then t2.vint end) c2,
max(case when t2.name = 'C1' then t2.vstring end) c1
from tab1 t left join
(select t2.*,
row_number() over (partition by name, id1
order by (case when root = 'A' then 1 else 0 end) desc
) as seqnum
from tab2 t2
) t2
on t.id1 = t2.id1 and
t.id2 = t2.id2 and
t2.seqnum = 1
group by t.id1, t.id2, t.a
答案 1 :(得分:0)
Gordon Linoff你的回答是正确的,但我没有办法让它变得更有活力。幸运的是,我发现了一个非常通用的解关键是将TAB1与分组的TAB2连接起来。
Select * from TAB2 A join
(Select ID1, ID2, MIN(ROOT), NAME from TAB2
group by ID2, ID1, NAME) B
on A.ID1 = B.ID1 and B.ID2 = A.ID2 and A.NAME = B.NAME