Группируйте несколько значений времени для каждого идентификатора как один период времени и отображайте каждый период времени с помощью SQL - PullRequest
0 голосов
/ 29 мая 2020

Есть ли способ решить следующую проблему в запросе SQL? Предположим, у вас есть следующая таблица в базе данных сервера Microsoft SQL:

date_time                         | tool_id
----------------------------------|-----------------
2020-02-18 12:00:00.0100000       | 4
2020-02-18 12:00:00.0200000       | 5
2020-02-18 12:00:00.0300000       | 5
2020-02-18 12:00:00.0400000       | 5
2020-02-18 12:00:00.0500000       | 7
2020-02-18 12:00:00.0600000       | 7
2020-02-18 12:00:00.0700000       | 7
2020-02-18 12:00:00.0800000       | 4
2020-02-18 12:00:00.0900000       | 4
2020-02-18 12:00:00.1000000       | 4

date_time - это дата и время в хронологическом порядке, а tool_id - это int, соответствующий определенный инструмент, который используется в машине в эту конкретную метку времени. Инструменты используются в станке в течение определенного периода времени (например, инструмент 7 используется с «2020-02-18 12: 00: 00.0500000» до «2020-02-18 12: 00: 00.0700000»). Моя цель сейчас состоит в том, чтобы в конечном итоге получить расписание для используемых инструментов в следующем формате в виде таблицы результатов:

tool_id | from_date_time                         | to_date_time
--------|----------------------------------------|-------------------------------
4       | 2020-02-18 12:00:00.0100000            | 2020-02-18 12:00:00.0100000
5       | 2020-02-18 12:00:00.0200000            | 2020-02-18 12:00:00.0400000
7       | 2020-02-18 12:00:00.0500000            | 2020-02-18 12:00:00.0700000
4       | 2020-02-18 12:00:00.0800000            | 2020-02-18 12:00:00.1000000

Результат должен отображаться в графическом веб-приложении da sh, поэтому предполагается для использования в контексте Python. Даже если есть решение для этого, просто используя SQL, может быть лучшее решение, сочетающее SQL и Python?

1 Ответ

0 голосов
/ 29 мая 2020

Предполагая, что ваш столбец «datetime» всегда имеет формат t_{int}, вы можете использовать STUFF, чтобы удалить первые 2 символа, а затем преобразовать это значение в int. Это позволяет вам упорядочить их численно, а не лексикографически. Затем вы можете получить MIN и MAX с решением для пробелов и островов и прочитать префикс t_:

WITH YourTable AS(
    SELECT *
    FROM (VALUES('t_1',4),
                ('t_3',5),
                ('t_4',5),
                ('t_5',5),
                ('t_6',7),
                ('t_7',7),
                ('t_8',7),
                ('t_9',4),
                ('t_10',4),
                ('t_11',4))V(date_time,toolid)),
CTE AS(
    SELECT YT.date_time,
           YT.toolid,
           V.time_int,
           ROW_NUMBER() OVER (ORDER BY V.time_int) - 
           ROW_NUMBER() OVER (PARTITION BY YT.toolid ORDER BY V.time_int) AS Grp
    FROM YourTable YT
         CROSS APPLY(VALUES(TRY_CONVERT(int,STUFF(date_time,1,2,''))))V(time_int))
SELECT C.toolid,
       CONCAT('t_',MIN(C.time_int)) AS From_date_time,
       CONCAT('t_',MAX(C.time_int)) AS To_date_time
FROM CTE C
GROUP BY C.toolid,
         C.Grp;

Изменить: непроверено, но на основе полностью измененного образца OP data это теперь просто проблема с пробелами и островком:

WITH CTE AS(
    SELECT YT.date_time,
           YT.toolid,
           ROW_NUMBER() OVER (ORDER BY YT.date_time) - 
           ROW_NUMBER() OVER (PARTITION BY YT.toolid ORDER BY YT.date_time) AS Grp
    FROM dbo.YourTable YT)
SELECT C.toolid,
       MIN(C.date_time) AS From_date_time,
       MAX(C.date_time) AS To_date_time
FROM CTE C
GROUP BY C.toolid,
         C.Grp;
...