2016-01-28 2 views
0

Я пытаюсь подсчитать разницу между двумя ВРЕМЯ, которые все сохранены в одной таблице, но и в разных строках и столбцах. Я использую SQL Server 2008 R2 Express (версия 10.50.2500.0) на платформе NT INTEL X86.SQL Server: зависимые подзапросы

У меня есть таблица так же, как этот:

CREATE TABLE TBL_DATA 
(
    id INT IDENTITY(1,1) PRIMARY KEY,     
    opid INT, 
    lotid INT,      
    dt_date DATE, 
    dt_begin_test TIME, 
    dt_end_test TIME 
); 

Эта таблица с загруженными данными /, например:

id  opid lotid dt_date  dt_begin_test  dt_end_test 
---------------------------------------------------------------------- 
5800 352 13381 2016-01-27 08:17:18.0000000 08:17:40.0000000 
5801 352 13381 2016-01-27 08:17:49.0000000 08:18:11.0000000 
5802 352 13381 2016-01-27 08:18:18.0000000 08:18:40.0000000 
5803 319 13381 2016-01-27 08:18:11.0000000 08:18:33.0000000 
5804 352 13381 2016-01-27 08:18:48.0000000 08:19:10.0000000 
5805 352 13381 2016-01-27 08:19:18.0000000 08:19:39.0000000 
5806 319 13381 2016-01-27 08:18:59.0000000 08:19:21.0000000 
5807 352 13381 2016-01-27 08:19:47.0000000 08:20:09.0000000 
5808 352 13381 2016-01-27 08:20:16.0000000 08:20:38.0000000 
5809 319 13381 2016-01-27 08:19:59.0000000 08:20:21.0000000 
5810 352 13381 2016-01-27 08:20:45.0000000 08:21:07.0000000 
5811 352 13381 2016-01-27 08:21:14.0000000 08:21:36.0000000 
5812 319 13381 2016-01-27 08:20:50.0000000 08:21:12.0000000 
5813 352 13381 2016-01-27 08:21:43.0000000 08:22:05.0000000 
5814 319 13381 2016-01-27 08:21:27.0000000 08:21:49.0000000 
5815 352 13381 2016-01-27 08:22:12.0000000 08:22:33.0000000 
5816 319 13381 2016-01-27 08:22:04.0000000 08:22:26.0000000 
5817 352 13381 2016-01-27 08:22:41.0000000 08:23:02.0000000 

То, что я хотел бы получить это выход для пользователя с opid=352, например, где мне нужно вычесть dt_begin_test значение строки 5805 от dt_end_test значение строки 5804, например. Результат должен быть 8 seconds. И сделайте это для всех линий пользователя с opid=352.

Существует очень красивое решение в случае, если бы было только одно значение opid в таблице TBL_DATA.

SELECT TBL_TEST.id, 
     TBL_TEST.opid, 
     TBL_TEST.lotid,   
     TBL_TEST.dt_date, 
     TBL_TEST.dt_begin_test, 
     TBL_TEST.dt_end_test,  
     COALESCE(
      DATEDIFF(
        second, (
        SELECT TBL_TMP.dt_end_test 
        FROM [TBL_DATA] AS TBL_TMP 
        WHERE TBL_TMP.id = TBL_TEST.id - 1),     
        TBL_TEST.dt_begin_test), 0) AS PAR_DEDUCT 
FROM [TBL_DATA] AS TBL_TEST 

К сожалению, это решение терпит неудачу, если вы должны вычесть значения из строк, которые не являются одним из следующих.

I случай:

SELECT TBL_TEST.id, 
     TBL_TEST.opid, 
     TBL_TEST.lotid,   
     TBL_TEST.dt_date, 
     TBL_TEST.dt_begin_test, 
     TBL_TEST.dt_end_test,  
     COALESCE(
      DATEDIFF(
        second, (
        SELECT TBL_TMP.dt_end_test 
        FROM [TBL_DATA] AS TBL_TMP 
        WHERE TBL_TMP.id = TBL_TEST.id - 1),     
        TBL_TEST.dt_begin_test), 0) AS PAR_DEDUCT 
FROM [TBL_DATA] AS TBL_TEST 
WHERE opid=352; 

он не работает правильно, что я понимаю.

Для этого у меня возникла идея, что я буду использовать функцию row_number(), чтобы создать новый столбец, а затем использовать другой вариант, чтобы сделать это. Немного измененный запрос SELECT:

SELECT *, 
COALESCE(DATEDIFF(second, 
     (SELECT dt_end_test FROM TBL_A AS TBL_TMP WHERE TBL_A.PAR_INDEX = TBL_TMP.PAR_INDEX - 1), 
       TBL_A.dt_begin_test), 0) AS PAR_DEDUCT 
FROM 
(SELECT row_number() OVER (ORDER BY TBL_TEST.id) AS PAR_INDEX, 
    TBL_TEST.id, 
    TBL_TEST.opid, 
    TBL_TEST.lotid, 
    TBL_TEST.dt_date, 
    TBL_TEST.dt_begin_test, 
    TBL_TEST.dt_end_test 
FROM [TBL_DATA] AS TBL_TEST 
WHERE opid=352 
) AS TBL_A; 

К сожалению, это не сработало. Он имеет проблему с параметром TBL_A в заявлении DATEDIFF ... SELECT.

Я могу сделать это по-другому. Я мог бы сохранить результаты во временной таблице, а затем сделать это, как указано выше. Я бы хотел сделать это в одном исполнении/команде.

Любая помощь очень ценится.

Tomas.

ответ

0

Возможно, вы сможете делать то, что хотите, используя Row_number в cte и левом, соединяющем его с собой.

;WITH cte AS (
    SELECT *, 
      ROW_NUMBER() OVER (PARTITION BY opid,lotid ORDER BY dt_date, dt_begin_test) Rn 
    FROM TBL_DATA 
) 
SELECT t1.*, 
     DATEDIFF(SECOND,t2.dt_end_test,t1.dt_begin_test) 
FROM cte t1 
     LEFT JOIN cte t2 ON t1.opid = t2.opid 
          AND t1.lotid = t2.lotid 
          AND t1.Rn - 1 = t2.Rn 
ORDER BY t1.opid, 
     t1.lotid, 
     t1.dt_date, 
     t1.dt_begin_test 
+0

Большое спасибо за помощь. После небольшой модификации она решила мою проблему! – Miky

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