我正在开发一个项目来为不同的订单创建SLA。要做到这一点,我需要将多行合并为一行,尽管有时它会超过1行。以下是当前数据的设置方式:
OrderNumber | Stage1 | Stage2 | Stage3 | Stage4 |
=================================================
1 |1/1/2016|*NULL* |*NULL* | *NULL*
1 |*NULL* |2/1/2016|*NULL* | *NULL*
1 |*NULL* |*NULL* |3/1/2016| *NULL*
1 |*NULL* |*NULL* |*NULL* | 4/1/2016
1 |*NULL* |5/1/2016|*NULL* | *NULL*
我希望看到数据的方式是这样的:
OrderNumber | Stage1 | Stage2 | Stage3 | Stage4 |
=================================================
1 |1/1/2016|2/1/2016|3/1/2016| 4/1/2016
1 |1/1/2016|5/1/2016|*NULL* | *NULL*
OR
OrderNumber | Stage1 | Stage2 | Stage3 | Stage4 |
=================================================
1 |1/1/2016|2/1/2016|3/1/2016| 4/1/2016
1 |*NULL* |5/1/2016|*NULL* | *NULL*
我看到两个问题,1)将多行合并到一行中2)如果一个值多次显示在一列中,则将其显示在一个新行中(理想情况下,前一个阶段中出现的值)列,但这不是必需的)。
我找到的最接近的解决方案是:Merge two rows in SQL,但它不适用于此问题。
非常感谢任何帮助。
编辑更新的标签
答案 0 :(得分:0)
我使用window functions
使用SQL Server 2012解决了这个问题。由于MySQL还支持窗口功能,因此它与哪个数据库无关。如果MySQL不支持CTE,您可以将其替换为派生表。
有4个阶段,所以我们需要4个加入。
;with cte as (
select t1.OrderNumber, t1.Stage1, t2.Stage2, t3.Stage3, t4.Stage4
, LAG(t1.Stage1) over (partition by t1.OrderNumber order by t1.Stage1) AS Prev1
, LAG(t2.Stage2) over (partition by t2.OrderNumber order by t2.Stage2) AS Prev2
, LAG(t3.Stage3) over (partition by t3.OrderNumber order by t3.Stage3) AS Prev3
, LAG(t4.Stage4) over (partition by t4.OrderNumber order by t4.Stage4) AS Prev4
from #t t1
inner join #t t2 on t2.OrderNumber = t1.OrderNumber and t2.Stage2 is not null
inner join #t t3 on t3.OrderNumber = t1.OrderNumber and t3.Stage3 is not null
inner join #t t4 on t4.OrderNumber = t1.OrderNumber and t4.Stage4 is not null
where t1.Stage1 is not null
)
select OrderNumber
, IIF(Stage1 <> Prev1 or Prev1 is null, Stage1, Null) AS Stage1
, IIF(Stage2 <> Prev2 or Prev2 is null, Stage2, Null) AS Stage2
, IIF(Stage3 <> Prev3 or Prev3 is null, Stage3, Null) AS Stage3
, IIF(Stage4 <> Prev4 or Prev4 is null, Stage4, Null) AS Stage4
from cte
将#t替换为您的表名
结果:
+-------------+------------+------------+------------+------------+
| OrderNumber | Stage1 | Stage2 | Stage3 | Stage4 |
+-------------+------------+------------+------------+------------+
| 1 | 2016-01-01 | 2016-01-02 | 2016-01-03 | 2016-01-04 |
| 1 | NULL | 2016-01-05 | NULL | NULL |
+-------------+------------+------------+------------+------------+
答案 1 :(得分:0)
您可以取消数据,然后再次转动
SELECT OrderNumber, [Stage1], [Stage2], [Stage3], [Stage4]
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Vals ORDER BY Val) Rn FROM
Table1 t
UNPIVOT
(
Val
FOR Vals IN ([Stage1], [Stage2], [Stage3], [Stage4])
) up
) t
PIVOT
(
MAX(Val)
FOR Vals IN ([Stage1], [Stage2], [Stage3], [Stage4])
) p
答案 2 :(得分:0)
with data as (
select
OrderNumber, Stage1, Stage2, Stage3, Stage4,
row_number() over (
partition by OrderNumber
order by
case when Stage1 is not null then 0 else 1 end, Stage1,
case when Stage2 is not null then 0 else 1 end, Stage2,
case when Stage3 is not null then 0 else 1 end, Stage3,
case when Stage4 is not null then 0 else 1 end, Stage4) rn,
row_number() over (
partition by OrderNumber
order by case when Stage1 is not null then 0 else 1 end, Stage1) r1,
row_number() over (
partition by OrderNumber
order by case when Stage2 is not null then 0 else 1 end, Stage2) r2,
row_number() over (
partition by OrderNumber
order by case when Stage3 is not null then 0 else 1 end, Stage3) r3,
row_number() over (
partition by OrderNumber
order by case when Stage4 is not null then 0 else 1 end, Stage4) r4
from T
)
select
OrderNumber, s1.Stage1, s2.Stage2, s3.Stage3, s4.Stage4
from
data d
cross apply (select d1.Stage1 from data d1 where d1.r1 = d.rn) s1(Stage1)
cross apply (select d2.Stage2 from data d2 where d2.r2 = d.rn) s2(Stage2)
cross apply (select d3.Stage3 from data d3 where d3.r3 = d.rn) s3(Stage3)
cross apply (select d4.Stage4 from data d4 where d4.r4 = d.rn) s4(Stage4)
where
coalesce(s1.Stage1, s2.Stage2, s3.Stage3, s4.Stage4) is not null