我有一个SQL表,其中一些事务处于父子关系中。但该关系仅由行和类型列确定。没有其他参考。我必须建立这个参考。
DECLARE @tmp TABLE (line INT, type CHAR(1), product VARCHAR(30))
INSERT @tmp VALUES
( 1,' ','22411')
,( 2,' ','22413')
,( 3,'P','27050')
,( 4,'C','22492')
,( 5,'C','22493')
,( 6,'C','22490')
,( 7,' ','22410')
,( 8,' ','22511')
,( 9,'P','27051')
,(10,'C','22470')
,(11,'C','22471')
,(12,'C','22473')
,(13,'C','22474')
,(14,' ','22015')
,(15,' ','22167')
,(16,' ','12411')
,(17,' ','22500')
第3行是父产品。第4行到第6行是子行。 第9行是另一个母产品。第10行到第13行是子行。
所需的输出是这样的,其中父子行被分组:
line|type|product|group
1 | |22411 |1
2 | |22413 |2
3 |P |27050 |3
4 |C |22492 |3
5 |C |22493 |3
6 |C |22490 |3
7 | |22410 |7
8 | |22511 |8
9 |P |27051 |9
10 |C |22470 |9
11 |C |22471 |9
12 |C |22473 |9
13 |C |22474 |9
14 | |22015 |14
15 | |22167 |15
16 | |12411 |16
17 | |22500 |17
如何在没有光标的情况下实现这一目标?
答案 0 :(得分:2)
如果输入始终有效,您可以使用以下查询。
SELECT *, RANK() OVER(ORDER BY gid) AS [group]
FROM
(
SELECT *, SUM(CASE WHEN type = 'C' AND (prev = 'P' OR prev = 'C') THEN 0 ELSE 1 END) OVER(ORDER BY line) AS gid
FROM
(
SELECT *, LAG(type) OVER(ORDER BY line) AS prev
FROM @tmp
) AS withPreviouLine
) AS grouped
它无法处理连续的C'没有' P'。从SQL SERVER 2012开始添加LAG。
答案 1 :(得分:1)
这几乎适用于所有版本的SQL Server,因为您没有指定正在使用的版本。
但是如果你至少使用SQL Server 2012,那么你可以使用@ qxg的解决方案,因为它更简单。
这是您需要的代码,虽然它不是单个查询,但它可以为您提供所需的结果:
CREATE TABLE #tmp (line INT, type CHAR(1), product VARCHAR(30))
INSERT #tmp VALUES ( 1,' ','22411')
,( 2,' ','22413')
,( 3,'P','27050')
,( 4,'C','22492')
,( 5,'C','22493')
,( 6,'C','22490')
,( 7,' ','22410')
,( 8,' ','22511')
,( 9,'P','27051')
,(10,'C','22470')
,(11,'C','22471')
,(12,'C','22473')
,(13,'C','22474')
,(14,' ','22015')
,(15,' ','22167')
,(16,' ','12411')
,(17,' ','22500')
select t1.*
, case
when t1.type = 'C'
and t3.type = ''
then 'G'
when t1.type = 'P' or t1.type = 'C'
then 'G'
else 'N'
end [same_group]
into #tmp2
from #tmp t1
left join #tmp t2 on t1.line = t2.line + 1
left join #tmp t3 on t1.line = t3.line - 1
order by t1.line
select *
, case
when t.type <> ''
then (select max(line)
from #tmp2
where same_group = 'G'
and type = 'P'
and line <= t.line)
else t.line
end [group_id]
from #tmp2 t
order by line
您可能会将其重构为单个查询,但目前我没有时间这样做。