2016-04-05 2 views
1

Я работаю над проектом создания SLA для разных заказов. Для этого мне нужно объединить несколько строк в одну строку, хотя бывают случаи, когда она будет более чем на 1 строку. Вот как данные в настоящее время создана:Объединение нескольких строк в одну строку (SQL)

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* 

ИЛИ

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* 

Есть две проблемы, I см. 1) Объединение нескольких строк в одну строку и 2) Если значение появляется в столбце более одного раза, отображение его в новой строке (в идеале со значениями предыдущих этапов, появляющимися в предыдущих столбцах, но это не требуется).

Самое близкое решение, которое я нашел, это: Merge two rows in SQL, но это не помогло решить эту проблему.

Любая помощь была бы принята с благодарностью.

Редактировать Обновленные теги

+1

, что произойдет, если 1-й этап имеет две не нулевые даты вместо одной? какой из них вы соедините с двумя этапами? –

+1

Возможный дубликат [Объединить несколько строк в одну строку] (http://stackoverflow.com/questions/10553198/merge-multiple-rows-into-a-singlerow) –

+0

Самый простой подход, который я могу придумать, - это назначить номер строки на каждый этап, когда значение не равно нулю. а затем присоединиться к данным на основе rownumber – xQbert

ответ

0

Я решить эту проблему с помощью SQL Server 2012, используя window functions. Поскольку 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  | 
+-------------+------------+------------+------------+------------+ 
+0

Похоже, он будет работать отлично.Спасибо, FLICKER! – Fowipple

0

Вы можете UNPIVOT данные, а затем поворота снова

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 
+0

@Fowipple Я действительно надеюсь, что вы проверите план выполнения, прежде чем просто использовать любой старый sql, который вы найдете в Интернете. – JamieD77

+0

Да, я не знаю, о чем я думал @ JamieD77. – shawnt00

+0

@ shawnt00 lol .. Я пытался заставить вашу работу работать, чтобы я мог видеть, как это будет сравнивать производительность, но я не мог понять это. Я полагал, что это будет лучше, чем выбранный ответ. – JamieD77

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 
+0

Что такое rdbms? – JamieD77

+0

@ JamieD77, OP сказал SQL Server. – shawnt00

+0

Вы пытались запустить это на сервере sql? – JamieD77

Смежные вопросы