Расширенная сортировка дат в SQL Server - PullRequest
1 голос
/ 17 мая 2019

Я сформировал набор результатов, как показано ниже, из 6 разных таблиц. У меня 6 разных дат.

enter image description here

Я должен получить набор результатов, как показано ниже.

enter image description here

Я пробовал с приведенным ниже кодом.

DECLARE @Input TABLE (
    year INT
    ,fmy CHAR(2)
    ,model CHAR(6)
    ,d1 DATE
    ,d2 DATE
    ,d3 DATE
    ,d4 DATE
    ,d5 DATE
    ,d6 DATE
    )
DECLARE @FinalResult TABLE (
    year INT
    ,fmy CHAR(2)
    ,model CHAR(6)
    ,d1 DATE
    ,d2 DATE
    ,d3 DATE
    ,d4 DATE
    ,d5 DATE
    ,d6 DATE
    )
DECLARE @year INT
    ,@fmy CHAR(2)
    ,@model CHAR(6)
    ,@d1 DATE
    ,@d2 DATE
    ,@d3 DATE
    ,@d4 DATE
    ,@d5 DATE
    ,@d6 DATE

INSERT INTO @Input
SELECT *
FROM (
    VALUES (
        2018
        ,'DD'
        ,'FCRAC2'
        ,'1/1/2018'
        ,'1/1/2018'
        ,'1/1/2018'
        ,'1/1/2018'
        ,'1/1/2018'
        ,'1/1/2018'
        )
        ,
        (
        2018
        ,'DD'
        ,'FCRAC2'
        ,'07/10/2018'
        ,NULL
        ,'01/08/2019'
        ,'03/01/2018'
        ,NULL
        ,NULL
        )
        ,(
        2018
        ,'DD'
        ,'FCRAC2'
        ,'09/05/2018'
        ,NULL
        ,NULL
        ,'07/03/2018'
        ,NULL
        ,NULL
        )
        ,(
         2018
        ,'DD'
        ,'FCRAC2'
        ,'01/08/2019'
        ,NULL
        ,NULL
        ,'01/08/2019'
        ,NULL
        ,NULL
        )
        --,(
        --2018
        --,'DD'
        --,'FCRAC2'
        --,'9/5/2018'
        --,NULL
        --,NULL
        --,NULL
        --,NULL
        --,NULL
        --)
    ) T(year, fmy, model, d1, d2, d3, d4, d5, d6)

DECLARE @datecount INT = 0
    ,@i INT = 1
    ,@outputdate DATE

--select *from (
--select distinct d1
--From @Input
--union 
--select distinct d2
--From @Input
--union 
--select distinct d3
--From @Input
--union 
--select distinct d4
--From @Input
--union 
--select distinct d5
--From @Input
--union 
--select distinct d6
--From @Input
--)T(dates)
--where dates is not null


DECLARE inputcursor CURSOR

FOR
SELECT *
FROM @Input

OPEN inputcursor

FETCH NEXT
FROM inputcursor
INTO @year
    ,@fmy
    ,@model
    ,@d1
    ,@d2
    ,@d3
    ,@d4
    ,@d5
    ,@d6

WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @datecount = count(DISTINCT dates)
    FROM (
        VALUES (@d1)
            ,(@d2)
            ,(@d3)
            ,(@d4)
            ,(@d5)
            ,(@d6)
        ) T(Dates)
    WHERE dates IS NOT NULL

    WHILE (@i <= @datecount)
    BEGIN
            ;

        WITH cte
        AS (
            SELECT dates
                ,row_number() OVER (
                    ORDER BY dates
                    ) rn
            FROM (
                SELECT DISTINCT dates
                FROM (
                    VALUES (@d1)
                        ,(@d2)
                        ,(@d3)
                        ,(@d4)
                        ,(@d5)
                        ,(@d6)
                    ) T(Dates)
                WHERE dates IS NOT NULL
                    --and id=@datecount
                ) d
            )
        SELECT @outputdate = dates
        FROM cte
        WHERE rn = @i           

        insert into @FinalResult 
        SELECT @year
            ,@fmy
            ,@model
            ,CASE 
                WHEN @d1 = @outputdate
                    THEN @d1
                ELSE NULL
                END
                ,CASE 
                WHEN @d2 = @outputdate
                    THEN @d2
                ELSE NULL
                END
                ,CASE 
                WHEN @d3 = @outputdate
                    THEN @d3
                ELSE NULL
                END
                ,CASE 
                WHEN @d4 = @outputdate
                    THEN @d4
                ELSE NULL
                END
                ,CASE 
                WHEN @d5 = @outputdate
                    THEN @d5
                ELSE NULL
                END
                ,CASE 
                WHEN @d6 = @outputdate
                    THEN @d6
                ELSE NULL
                END

        SET @i = @i + 1
    END

    SET @i = 1

    FETCH NEXT
    FROM inputcursor
    INTO @year
        ,@fmy
        ,@model
        ,@d1
        ,@d2
        ,@d3
        ,@d4
        ,@d5
        ,@d6
END

CLOSE inputcursor

DEALLOCATE inputcursor

select *from @Input

select * from @FinalResult

Я сам ввел входные данные в виде SQL в самом коде.

Это работает для этого набора результатов, но тот же код не работает для ввода ниже.

enter image description here

Я пытаюсь найти любой другой способ сделать это без использования циклов. У меня тысяча с лишним моделей, у каждой модели от 10 до 20 записей. Я дал примерный набор записей для одной модели.

Для окончательного набора результатов необходимо учитывать следующее.

  1. Если все 6 дат одинаковы для конкретной модели, мы можем показать ее в одной строке.

  2. Даты должны быть в отсортированном порядке. скажем, для строки № 2 у нас есть три даты. поэтому мы должны отобразить его в трех строках под соответствующим столбцом, учитывая, что окончательный полный набор результатов будет отсортирован.

1 Ответ

0 голосов
/ 17 мая 2019

Один из методов - получить список различных дат из вашей таблицы и выполнить LEFT JOIN обратно в таблицу.Затем вы можете использовать выражение CASE, чтобы отображать дату только в том случае, если она совпадает со значением этой строки:

DECLARE @Input table (year int,
                      fmy char(2),
                      model char(6),
                      d1 date,
                      d2 date,
                      d3 date,
                      d4 date,
                      d5 date,
                      d6 date);

INSERT INTO @Input
SELECT T.year,
       T.fmy,
       T.model,
       CONVERT(date,T.d1,101),
       CONVERT(date,T.d2,101),
       CONVERT(date,T.d3,101),
       CONVERT(date,T.d4,101),
       CONVERT(date,T.d5,101),
       CONVERT(date,T.d6,101)
FROM (VALUES (2018, 'DD', 'FCRAC1', '1/1/2017', '1/1/2017', '1/1/2017', '1/1/2017', '1/1/2017', '1/1/2017'),
             (2018, 'DD', 'FCRAC1', '1/8/2018', '12/31/2017', NULL, '1/8/2018', NULL, NULL),
             (2018, 'DD', 'FCRAC1', '5/24/2018', NULL, NULL, '3/1/2018', NULL, NULL),
             (2018, 'DD', 'FCRAC1', '7/3/2018', NULL, NULL, '7/3/2018', NULL, NULL),
             (2018, 'DD', 'FCRAC1', '9/5/2018', NULL, NULL, NULL, NULL, NULL)) AS T (year, fmy, model, d1, d2, d3, d4, d5, d6);

WITH Dates AS(
    SELECT DISTINCT D
    FROM @Input
         CROSS APPLY (VALUES(d1),(d2),(d3),(d4),(d5),(d6)) V(D))
SELECT I.[year],
       I.fmy,
       I.model,
       CASE D.D WHEN I.d1 THEN I.d1 END AS d1,
       CASE D.D WHEN I.d2 THEN I.d2 END AS d2,
       CASE D.D WHEN I.d3 THEN I.d3 END AS d3,
       CASE D.D WHEN I.d4 THEN I.d4 END AS d4,
       CASE D.D WHEN I.d5 THEN I.d5 END AS d5,
       CASE D.D WHEN I.d6 THEN I.d6 END AS d6
FROM Dates D
     LEFT JOIN @Input I ON D.D IN (I.D1,I.D2,I.D3,I.D4,I.D5,I.D6)
WHERE D.D != '20180905' --As this wasn't in your expected results, assumed filter out
ORDER BY D.D;

Примечание. Это вряд ли будет эффективно при большом наборе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...