SQL Server:依赖子查询

时间:2016-01-28 19:07:12

标签: sql sql-server sql-server-2008-r2

我正在尝试计算两个TIME之间的差异(扣除),这两个TIME都保存在一个表中,但也存储在不同的行和列中。我在NT INTEL X86平台上使用SQL Server 2008 R2 Express(版本10.50.2500.0)。

我有一张像这样的桌子:

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_test5804的值例如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 值,则有一个非常漂亮的解决方案。

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 *, 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; 函数创建一个新列,然后使用另一个选择来执行它。稍微修改SELECT查询如下:

TBL_A

不幸的是它不起作用。 DATEDIFF ... SELECT语句中的{{1}}参数存在问题。

我可以用另一种方式做到。我可以将结果保存在临时表中,然后按照上面的说明进行操作。我想要的是在一个执行/命令中执行它。

非常感谢任何帮助。

托马斯。

1 个答案:

答案 0 :(得分:0)

您可以在cte中使用Row_number执行您想要的操作,然后将其连接到自身。

;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