Как написать запрос для проблемы пробелов и островов? - PullRequest
0 голосов
/ 01 октября 2018

Это проблема пробелов и островков.

Meter_id |Realtimeclock      |I_Y|I_B|I_X|
201010   |27-09-2018 00:00:00|1.0|2.0|3.0|
201010   |27-09-2018 00:30:00|1.0|2.0|3.0|
201010   |27-09-2018 01:00:00|1.0|2.0|3.0|
201010   |27-09-2018 01:30:00|1.0|2.0|3.0|
201010   |27-09-2018 02:00:00|1.0| 0 |3.0|
201010   |27-09-2018 02:30:00|1.0| 0 |0  |
201010   |27-09-2018 03:00:00|1.0|2.0|3.0|
201010   |27-09-2018 03:30:00|1.0|2.0|3.0|
201011   |27-09-2018 00:00:00|1.0|2.0|3.0|
201011   |27-09-2018 00:30:00|1.0|2.0|3.0|
201010   |28-09-2018 03:00:00|1.0|2.0|3.0|
201010   |28-09-2018 03:30:00|1.0|2.0|3.0|
201011   |28-09-2018 04:00:00|1.0| 0 |0  |
201011   |28-09-2018 00:00:00|1.0|2.0|3.0|
201011   |28-09-2018 00:30:00|1.0|2.0|3.0|

В одном из подходов используется метод разницы в числах строк:

select * from (
WITH cte1 AS (
        SELECT t.*, ROW_NUMBER() OVER (PARTITION BY Meter_id ORDER BY Realtimeclock) rn
        FROM yourTable t
    ),
    cte2 AS (
        SELECT t.*, ROW_NUMBER() OVER (PARTITION BY Meter_id ORDER BY Realtimeclock) rn
        FROM yourTable t
        WHERE I_B <> 0
    ),
    cte3 AS (
        SELECT t1.*,
            t1.rn - t2.rn AS diff
        FROM cte1 t1
        INNER JOIN cte2 t2
            ON t1.Meter_id = t2.Meter_id AND t1.Realtimeclock = t2.Realtimeclock
    )        
    SELECT
        Meter_id,
        MIN(Realtimeclock) AS start_time,
        MAX(Realtimeclock) AS end_time,
        COUNT(I_Y) AS I_Y,
        COUNT(I_B) AS I_B,
        COUNT(I_X) AS I_X,ROW_NUMBER() OVER (PARTITION BY meter_id ORDER BY meter_id ) AS Spell
    FROM cte3
    GROUP BY
        Meter_id,
        diff);

Вывод должен выводиться наподобие ,, Пожалуйста, дайте мне знатьлюбое изменение, требуемое в коде.

Из приведенной выше таблицы мне нужны дневные заклинания как время начала и время окончания, основанные на условии I_Y, I_B, I_X, которое является ненулевым значением как счетное.Здесь мы видим, что время начала 201010 метра имеет два заклинания, поскольку между ними был промежуток времени.Кроме того, он должен показать все заклинания вместе с датой и отметкой времени.

Meter_id |start_time         |End_time           |I_Y|I_B|I_X|spell
201010   |27-09-2018 00:00:00|27-09-2018 01:30:00|4  |4  |4  |1
201010   |27-09-2018 03:00:00|27-09-2018 03:30:00|4  |4  |4  |2
201011   |27-09-2018 00:00:00|27-09-2018 00:30:00|2  |2  |2  |1
201010   |28-09-2018 03:00:00|27-09-2018 03:30:00|2  |2  |2  |1
201011   |28-09-2018 00:00:00|28-09-2018 00:30:00|2  |2  |2  |1

Ошибка времени выполнения броска, как показано ниже,

[Ошибка] Выполнение (35: 22): ORA-01830:Изображение в формате даты заканчивается перед преобразованием всей входной строки

Привет, Тим,

Пожалуйста, посмотрите на это. Это мне очень поможет.

Вышеприведенное снятопосле передачи trunc (realtimeclock) вместо TO_DATE (realtimeclock) ..

Спасибо за помощь, Тим.

1 Ответ

0 голосов
/ 01 октября 2018

Вам нужно лишь небольшое изменение вашего текущего подхода, чтобы добавить раздел на дату (в дополнение к meter_id).Затем в последнем запросе добавьте COUNT, который подсчитывает количество заклинаний для данного метра и даты.

WITH cte1 AS (
    SELECT t.*,
        ROW_NUMBER() OVER (PARTITION BY Meter_id, TO_DATE(Realtimeclock)
            ORDER BY Realtimeclock) rn
    FROM yourTable t
),
cte2 AS (
    SELECT t.*,
        ROW_NUMBER() OVER (PARTITION BY Meter_id, TO_DATE(Realtimeclock)
            ORDER BY Realtimeclock) rn
    FROM yourTable t
    WHERE I_B <> 0
),
cte3 AS (
    SELECT t1.*,
        t1.rn - t2.rn AS diff
    FROM cte1 t1
    INNER JOIN cte2 t2
        ON t1.Meter_id = t2.Meter_id AND t1.Realtimeclock = t2.Realtimeclock
)

SELECT
    Meter_id,
    MIN(Realtimeclock) AS start_time,
    MAX(Realtimeclock) AS end_time,
    COUNT(I_Y) AS I_Y,
    COUNT(I_B) AS I_B,
    COUNT(I_X) AS I_X,
    COUNT(*) OVER (PARTITION BY TO_DATE(Realtimeclock), Meter_id
        ORDER BY MIN(Realtimeclock)) AS spell
FROM cte3
GROUP BY
    Meter_id,
    TO_DATE(Realtimeclock),
    diff;

enter image description here

Демонстрация

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

Демонстрация снова в SQL Server, хотя приведенный выше запрос является кодом Oracle и должен выполняться безлюбые вопросы.

...