使用SQL Server 2008中的Date函数进行计算

时间:2016-11-28 11:56:33

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

我正在为一组TO_DATEBINGIDINDUSID计算COMP1列。

IsRowActive = 1然后TO_DATE =“9999-12-31”时,正确返回。

但是当IsRowActive = 0时,我们必须计算To_Date,它应该比下一个FROMDT小1秒

数据:

    DECLARE @MYTABLE TABLE

(
BINGID INT,
INDUSID INT,
DTSEARCH DATETIME2,
COMP1 VARCHAR (100),
LISTPRICE NUMERIC(10,2),
FROMDT DATETIME2,
IsRowActive INT

)
INSERT @MYTABLE

SELECT 1002285, 1002,   '2016-03-03 04:10:58.0000000',  '0026PU009163-031', '77.7600',  '2015-12-19 12:51:49.0000000',0 UNION ALL
SELECT 1002285, 1002,   '2016-05-27 12:14:53.0000000',  '0026PU009163-031', '85.2200',  '2016-05-27 12:14:53.0000000',0 UNION ALL
SELECT 1002285, 1002,   '2016-07-20 06:44:37.0000000',  '0026PU009163-031', '90.3900',  '2016-07-20 06:44:37.0000000',0 UNION ALL
SELECT 1002285, 1002,   '2016-11-09 13:37:13.0000000',  '0026PU009163-031', '131.4500', '2016-10-18 13:49:10.0000000',1 UNION ALL
SELECT 1002285, 1002,   '2015-12-19 12:51:41.0000000',  '10122374', 65.1400,    '2015-12-19 12:51:41.0000000',  0  UNION ALL
SELECT 1002285, 1002,   '2016-03-03 04:11:01.0000000',  '10122374', 117.2100,   '2016-03-03 04:11:01.0000000',  0  UNION ALL
SELECT 1002285, 1002,   '2016-05-27 12:14:45.0000000',  '10122374', 53.5500,    '2016-05-27 12:14:45.0000000',  0  UNION ALL
SELECT 1002285, 1002,   '2016-07-20 06:44:29.0000000',  '10122374', 48.5000,    '2016-07-20 06:44:29.0000000',  0  UNION ALL
SELECT 1002285, 1002,   '2016-10-18 13:49:00.0000000',  '10122374', 75.6800,    '2016-10-18 13:49:00.0000000',  0  UNION ALL
SELECT 1002285, 1002,   '2016-11-09 13:37:02.0000000',  '10122374', 68.2400,    '2016-11-09 13:37:02.0000000',  1 UNION ALL

SELECT 1000001, 1002,   '2016-03-03 02:22:09.0000000',  '161GDB1577',   37.1700,    '2015-12-18 06:45:05.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-03-03 02:22:18.0000000',  '0392347402',   41.9100,    '2015-12-18 06:45:14.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-05-26 14:54:28.0000000',  '161GDB1577',   46.7100,    '2016-05-26 14:54:28.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-05-26 14:54:42.0000000',  '0392347402',   54.7100,    '2016-05-26 14:54:42.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-07-15 06:34:33.0000000',  '161GDB1577',   52.4800,    '2016-07-15 06:34:33.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-07-15 06:34:45.0000000',  '0392347402',   81.7100,    '2016-07-15 06:34:45.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-10-17 11:26:45.0000000',  '161GDB1577',   61.6400,    '2016-10-17 11:26:45.0000000',0  UNION ALL
SELECT 1000001, 1002,   '2016-11-09 02:21:17.0000000',  '0392347402',   81.9200,    '2016-10-17 11:26:58.0000000',1  UNION ALL
SELECT 1000001, 1002,   '2016-11-09 02:21:05.0000000',  '161GDB1577',   78.3500,    '2016-11-09 02:21:05.0000000',1  UNION ALL
SELECT 1000005, 1002,   '2018-11-09 02:21:05.0000000',  '556556GHB',    78.3500,    '2018-11-09 02:21:05.0000000',1

我试过查询 - 遗憾的是它返回了错误的数据:

SELECT
    BINGID, INDUSID, DTSEARCH,  
    COMP1, LISTPRICE, FROMDT,
    CASE 
       WHEN IsRowActive = 1 
          THEN '9999-12-31' 
          ELSE TO_DATE 
    END AS TO_DATE,
    IsRowActive
FROM 
    @MYTABLE mt
OUTER APPLY 
    (SELECT  
         MAX(DATEADD(second, -1, FROMDT)) TO_DATE 
     FROM   
         @MYTABLE mt2 
     WHERE   
         mt2.BINGID = mt.BINGID 
         AND mt2.INDUSID = mt.INDUSID 
         AND mt2.FROMDT > mt.FROMDT) oa
WHERE 
    mt.INDUSID = '1002'  

预期输出

  BINGID    INDUSID DTSEARCH    COMP1   LISTPRICE   FROMDT  NEW_TO_DATE IsRowCurrent
1000001 1002    2016-03-03 02:22:09.0000000 161GDB1577  37.1700 2015-12-18 06:45:05.0000000 2016-05-26 14:54:27.0000000 0
1000001 1002    2016-03-03 02:22:18.0000000 0392347402  41.9100 2015-12-18 06:45:14.0000000 2016-05-26 14:54:41.0000000 0
1000001 1002    2016-05-26 14:54:28.0000000 161GDB1577  46.7100 2016-05-26 14:54:28.0000000 2016-07-15 06:34:32.0000000 0
1000001 1002    2016-05-26 14:54:42.0000000 0392347402  54.7100 2016-05-26 14:54:42.0000000 2016-07-15 06:34:44.0000000 0
1000001 1002    2016-07-15 06:34:33.0000000 161GDB1577  52.4800 2016-07-15 06:34:33.0000000 2016-10-17 11:26:44.0000000 0
1000001 1002    2016-07-15 06:34:45.0000000 0392347402  81.7100 2016-07-15 06:34:45.0000000 2016-10-17 11:26:57.0000000 0
1000001 1002    2016-10-17 11:26:45.0000000 161GDB1577  61.6400 2016-10-17 11:26:45.0000000 2016-11-09 02:21:04.0000000 0
1000001 1002    2016-11-09 02:21:17.0000000 0392347402  81.9200 2016-10-17 11:26:58.0000000 9999-12-31 00:00:00.0000000 1
1000001 1002    2016-11-09 02:21:05.0000000 161GDB1577  78.3500 2016-11-09 02:21:05.0000000 9999-12-31 00:00:00.0000000 1
1000005 1002    2018-11-09 02:21:05.0000000 556556GHB   78.3500 2018-11-09 02:21:05.0000000 9999-12-31 00:00:00.0000000 1
1002285,    1002,   '2016-03-03 04:10:58.0000000',  '0026PU009163-031', '77.7600',  2015-12-19 12:51:49.0000000'    2016-05-27 12:14:52.0000000'    0
1002285,    1002,   '2016-05-27 12:14:53.0000000',  '0026PU009163-031', '85.2200',  2016-05-27 12:14:53.0000000'    2016-07-20 06:44:36.0000000'    0
1002285,    1002,   '2016-07-20 06:44:37.0000000',  '0026PU009163-031', '90.3900',  2016-07-20 06:44:37.0000000'    2016-10-18 13:49:09.0000000'    0
1002285,    1002,   '2016-11-09 13:37:13.0000000',  '0026PU009163-031', '131.4500', 2016-10-18 13:49:10.0000000'    9999-12-31 00:00:00.0000000 1
1002285,    1002,   '2015-12-19 12:51:41.0000000',  '10122374', 65.1400,    '2015-12-19 12:51:41.0000000',  2016-03-03 04:11:00.0000000',   0
1002285,    1002,   '2016-03-03 04:11:01.0000000',  '10122374', 117.2100,   '2016-03-03 04:11:01.0000000',  2016-05-27 12:14:44.0000000',   0
1002285,    1002,   '2016-05-27 12:14:45.0000000',  '10122374', 53.5500,    '2016-05-27 12:14:45.0000000',  2016-07-20 06:44:28.0000000',   0
1002285,    1002,   '2016-07-20 06:44:29.0000000',  '10122374', 48.5000,    '2016-07-20 06:44:29.0000000',  2016-10-18 13:48:59.0000000',   0
1002285,    1002,   '2016-10-18 13:49:00.0000000',  '10122374', 75.6800,    '2016-10-18 13:49:00.0000000',  2016-11-09 13:37:01.0000000',   0
1002285,    1002,   '2016-11-09 13:37:02.0000000',  '10122374', 68.2400,    '2016-11-09 13:37:02.0000000',  9999-12-31 00:00:00.0000000 1

感谢。

5 个答案:

答案 0 :(得分:2)

试试这个简单易读的解决方案,使用CTESelf Join

with cte as  
( 
  SELECT
  ROW_NUMBER() over (order by BINGID,INDUSID,DTSEARCH,COMP1,LISTPRICE,FROMDT) 
      as rowno, -- It is good if you have identity column here
      BINGID,
      INDUSID,    
      DTSEARCH,   
      COMP1,  
      LISTPRICE,  
      FROMDT,
      IsRowActive
      FROM @MYTABLE mt 
)
select c1.*,
 CASE WHEN c1.IsRowActive = 1 THEN '9999-12-31' ELSE DATEADD(second, -1, c2.FROMDT) END
 AS TO_DATE
 from cte c1 left join cte c2
 on c1.rowno+1 = c2.rowno 

答案 1 :(得分:2)

我真的很喜欢@Chanukya的回答。但是当您使用2008时,您将无法使用LEAD功能。相反,您可以使用自联接:

-- SQL Server 2008.
SELECT
    c.*,
    CASE c.IsRowActive 
        WHEN 1 THEN '9999-12-31'
        ELSE DATEADD(SECOND, -1, MIN(p.FROMDT))
    END AS TO_DATE
FROM
    @MYTABLE AS c
        LEFT OUTER JOIN @MYTABLE AS p       ON  p.BINGID    = c.BINGID
                                            AND p.INDUSID   = c.INDUSID
                                            AND p.FROMDT    > c.FROMDT
GROUP BY
    c.BINGID,
    c.INDUSID,
    c.DTSEARCH,
    c.COMP1,
    c.LISTPRICE,
    c.FROMDT,
    c.IsRowActive
ORDER BY
    c.FROMDT
;

逻辑类似于你的外部应用,但它应该表现得更好。这是因为没有correlation

样本数据提出了一个小挑战。因为有两个FROMDT 2016-07-20 06:44:37.0000000的记录,你可以说我的结果是错误的。

答案 2 :(得分:1)

DECLARE @MYTABLE TABLE
(
BINGID  int,
INDUSID int,
DTSEARCH datetime2, 
COMP1 varchar(100),
LISTPRICE numeric(15,5),    
FROMDT  datetime2,
IsRowActive int

)
insert @MYTABLE

SELECT 1002285  ,1002   ,'2016-03-03 04:10:58.0000000', '0026PU009163-031', 77.7600 ,'2015-12-19 12:51:49.0000000', 0 UNION ALL
SELECT 1002285  ,1002   ,'2016-05-27 12:14:53.0000000', '0026PU009163-031', 85.2200 ,'2016-05-27 12:14:53.0000000', 0  UNION ALL
SELECT 1002285  ,1002   ,'2016-07-20 06:44:37.0000000', '0026PU009163-031', 90.3900 ,'2016-07-20 06:44:37.0000000', 0  UNION ALL
SELECT 1002285  ,1002   ,'2016-11-09 13:37:13.0000000', '0026PU009163-031', 131.4500,'2016-07-20 06:44:37.0000000', 1


select BINGID,DTSEARCH,COMP1,LISTPRICE,FROMDT,CASE WHEN IsRowActive = 0 THEN lead(DATEADD(SS,-1,FROMDT)) OVER (ORDER BY FROMDT) ELSE  '9999-12-31' END AS expected_date

FROM @MYTABLE mt

输出

BINGID  DTSEARCH    COMP1   LISTPRICE   FROMDT  expected_date
1002285 2016-03-03 04:10:58.0000000 0026PU009163-031    77.76000    2015-12-19 12:51:49.0000000 2016-05-27 12:14:52.0000000
1002285 2016-05-27 12:14:53.0000000 0026PU009163-031    85.22000    2016-05-27 12:14:53.0000000 2016-07-20 06:44:36.0000000
1002285 2016-07-20 06:44:37.0000000 0026PU009163-031    90.39000    2016-07-20 06:44:37.0000000 2016-07-20 06:44:36.0000000
1002285 2016-11-09 13:37:13.0000000 0026PU009163-031    131.45000   2016-07-20 06:44:37.0000000 9999-12-31 00:00:00.0000000

答案 3 :(得分:1)

而不是<?php function hide_error() { ?> <style type="text/css"> .login #login_error{ display: none; } </style> <?php } add_action( 'login_enqueue_scripts', 'hide_error' ); ?> MAX中使用TOP(1)ORDER BY使用OUTER APPLY

另外,您说要按BINGID, INDUSID, COMP1进行分组,因此请使用WHEREOUTER APPLY子句中的所有这些列。为什么在查询中省略COMP1

示例数据

DECLARE @MYTABLE TABLE
(
    BINGID INT,
    INDUSID INT,
    DTSEARCH DATETIME2,
    COMP1 VARCHAR (100),
    LISTPRICE NUMERIC(10,2),
    FROMDT DATETIME2,
    IsRowActive INT
)

INSERT INTO @MYTABLE
SELECT 1002285, 1002, '2016-03-03 04:10:58', '0026PU009163-031',  77.7600, '2015-12-19 12:51:49', 0 UNION ALL
SELECT 1002285, 1002, '2016-05-27 12:14:53', '0026PU009163-031',  85.2200, '2016-05-27 12:14:53', 0 UNION ALL
SELECT 1002285, 1002, '2016-07-20 06:44:37', '0026PU009163-031',  90.3900, '2016-07-20 06:44:37', 0 UNION ALL
SELECT 1002285, 1002, '2016-11-09 13:37:13', '0026PU009163-031', 131.4500, '2016-10-18 13:49:10', 1 UNION ALL
SELECT 1002285, 1002, '2015-12-19 12:51:41', '10122374',          65.1400, '2015-12-19 12:51:41', 0 UNION ALL
SELECT 1002285, 1002, '2016-03-03 04:11:01', '10122374',         117.2100, '2016-03-03 04:11:01', 0 UNION ALL
SELECT 1002285, 1002, '2016-05-27 12:14:45', '10122374',          53.5500, '2016-05-27 12:14:45', 0 UNION ALL
SELECT 1002285, 1002, '2016-07-20 06:44:29', '10122374',          48.5000, '2016-07-20 06:44:29', 0 UNION ALL
SELECT 1002285, 1002, '2016-10-18 13:49:00', '10122374',          75.6800, '2016-10-18 13:49:00', 0 UNION ALL
SELECT 1002285, 1002, '2016-11-09 13:37:02', '10122374',          68.2400, '2016-11-09 13:37:02', 1 UNION ALL
SELECT 1000001, 1002, '2016-03-03 02:22:09', '161GDB1577',        37.1700, '2015-12-18 06:45:05', 0 UNION ALL
SELECT 1000001, 1002, '2016-03-03 02:22:18', '0392347402',        41.9100, '2015-12-18 06:45:14', 0 UNION ALL
SELECT 1000001, 1002, '2016-05-26 14:54:28', '161GDB1577',        46.7100, '2016-05-26 14:54:28', 0 UNION ALL
SELECT 1000001, 1002, '2016-05-26 14:54:42', '0392347402',        54.7100, '2016-05-26 14:54:42', 0 UNION ALL
SELECT 1000001, 1002, '2016-07-15 06:34:33', '161GDB1577',        52.4800, '2016-07-15 06:34:33', 0 UNION ALL
SELECT 1000001, 1002, '2016-07-15 06:34:45', '0392347402',        81.7100, '2016-07-15 06:34:45', 0 UNION ALL
SELECT 1000001, 1002, '2016-10-17 11:26:45', '161GDB1577',        61.6400, '2016-10-17 11:26:45', 0 UNION ALL
SELECT 1000001, 1002, '2016-11-09 02:21:17', '0392347402',        81.9200, '2016-10-17 11:26:58', 1 UNION ALL
SELECT 1000001, 1002, '2016-11-09 02:21:05', '161GDB1577',        78.3500, '2016-11-09 02:21:05', 1 UNION ALL
SELECT 1000005, 1002, '2018-11-09 02:21:05', '556556GHB',         78.3500, '2018-11-09 02:21:05', 1

<强>查询

SELECT
    BINGID,
    INDUSID,
    DTSEARCH,
    COMP1,
    LISTPRICE,
    FROMDT,
    CASE WHEN IsRowActive = 1 THEN '9999-12-31' ELSE oa.TO_DATE END AS TO_DATE,
    IsRowActive
FROM
    @MYTABLE AS mt
    OUTER APPLY 
    (   
        SELECT TOP(1) DATEADD(second, -1, FROMDT) AS TO_DATE
        FROM @MYTABLE AS mt2
        WHERE
            mt2.BINGID = mt.BINGID 
            AND mt2.INDUSID = mt.INDUSID 
            AND mt2.COMP1 = mt.COMP1
            AND mt2.FROMDT > mt.FROMDT
        ORDER BY mt2.FROMDT
    ) AS oa
WHERE
    mt.INDUSID = '1002'
ORDER BY BINGID, INDUSID, COMP1, FROMDT;

<强>结果

+---------+---------+-----------------------------+------------------+-----------+-----------------------------+-----------------------------+-------------+
| BINGID  | INDUSID |          DTSEARCH           |      COMP1       | LISTPRICE |           FROMDT            |           TO_DATE           | IsRowActive |
+---------+---------+-----------------------------+------------------+-----------+-----------------------------+-----------------------------+-------------+
| 1000001 |    1002 | 2016-03-03 02:22:18.0000000 | 0392347402       | 41.91     | 2015-12-18 06:45:14.0000000 | 2016-05-26 14:54:41.0000000 |           0 |
| 1000001 |    1002 | 2016-05-26 14:54:42.0000000 | 0392347402       | 54.71     | 2016-05-26 14:54:42.0000000 | 2016-07-15 06:34:44.0000000 |           0 |
| 1000001 |    1002 | 2016-07-15 06:34:45.0000000 | 0392347402       | 81.71     | 2016-07-15 06:34:45.0000000 | 2016-10-17 11:26:57.0000000 |           0 |
| 1000001 |    1002 | 2016-11-09 02:21:17.0000000 | 0392347402       | 81.92     | 2016-10-17 11:26:58.0000000 | 9999-12-31 00:00:00.0000000 |           1 |
| 1000001 |    1002 | 2016-03-03 02:22:09.0000000 | 161GDB1577       | 37.17     | 2015-12-18 06:45:05.0000000 | 2016-05-26 14:54:27.0000000 |           0 |
| 1000001 |    1002 | 2016-05-26 14:54:28.0000000 | 161GDB1577       | 46.71     | 2016-05-26 14:54:28.0000000 | 2016-07-15 06:34:32.0000000 |           0 |
| 1000001 |    1002 | 2016-07-15 06:34:33.0000000 | 161GDB1577       | 52.48     | 2016-07-15 06:34:33.0000000 | 2016-10-17 11:26:44.0000000 |           0 |
| 1000001 |    1002 | 2016-10-17 11:26:45.0000000 | 161GDB1577       | 61.64     | 2016-10-17 11:26:45.0000000 | 2016-11-09 02:21:04.0000000 |           0 |
| 1000001 |    1002 | 2016-11-09 02:21:05.0000000 | 161GDB1577       | 78.35     | 2016-11-09 02:21:05.0000000 | 9999-12-31 00:00:00.0000000 |           1 |
| 1000005 |    1002 | 2018-11-09 02:21:05.0000000 | 556556GHB        | 78.35     | 2018-11-09 02:21:05.0000000 | 9999-12-31 00:00:00.0000000 |           1 |
| 1002285 |    1002 | 2016-03-03 04:10:58.0000000 | 0026PU009163-031 | 77.76     | 2015-12-19 12:51:49.0000000 | 2016-05-27 12:14:52.0000000 |           0 |
| 1002285 |    1002 | 2016-05-27 12:14:53.0000000 | 0026PU009163-031 | 85.22     | 2016-05-27 12:14:53.0000000 | 2016-07-20 06:44:36.0000000 |           0 |
| 1002285 |    1002 | 2016-07-20 06:44:37.0000000 | 0026PU009163-031 | 90.39     | 2016-07-20 06:44:37.0000000 | 2016-10-18 13:49:09.0000000 |           0 |
| 1002285 |    1002 | 2016-11-09 13:37:13.0000000 | 0026PU009163-031 | 131.45    | 2016-10-18 13:49:10.0000000 | 9999-12-31 00:00:00.0000000 |           1 |
| 1002285 |    1002 | 2015-12-19 12:51:41.0000000 | 10122374         | 65.14     | 2015-12-19 12:51:41.0000000 | 2016-03-03 04:11:00.0000000 |           0 |
| 1002285 |    1002 | 2016-03-03 04:11:01.0000000 | 10122374         | 117.21    | 2016-03-03 04:11:01.0000000 | 2016-05-27 12:14:44.0000000 |           0 |
| 1002285 |    1002 | 2016-05-27 12:14:45.0000000 | 10122374         | 53.55     | 2016-05-27 12:14:45.0000000 | 2016-07-20 06:44:28.0000000 |           0 |
| 1002285 |    1002 | 2016-07-20 06:44:29.0000000 | 10122374         | 48.50     | 2016-07-20 06:44:29.0000000 | 2016-10-18 13:48:59.0000000 |           0 |
| 1002285 |    1002 | 2016-10-18 13:49:00.0000000 | 10122374         | 75.68     | 2016-10-18 13:49:00.0000000 | 2016-11-09 13:37:01.0000000 |           0 |
| 1002285 |    1002 | 2016-11-09 13:37:02.0000000 | 10122374         | 68.24     | 2016-11-09 13:37:02.0000000 | 9999-12-31 00:00:00.0000000 |           1 |
+---------+---------+-----------------------------+------------------+-----------+-----------------------------+-----------------------------+-------------+

答案 4 :(得分:-1)

使用CTE +联接:

最后,解决方案就在这里。 结果数据最终根据您的要求准确,您也可以使用[列名]的顺序更改序列。

代码:

      with cte as  
                ( 
                      SELECT 
                      ROW_NUMBER( ) OVER ( partition by  COMP1 ORDER BY (SELECT 1))
                      rowno,
                      BINGID,
                      INDUSID,    
                      DTSEARCH,   
                      COMP1,  
                      LISTPRICE,  
                      FROMDT,
                      IsRowActive
                      FROM @MYTABLE mt 
                )
                select c1.BINGID,c1.INDUSID, c1.DTSEARCH,  c1.COMP1, c1.LISTPRICE, c1.FROMDT, c1.IsRowActive,
                CASE WHEN c1.IsRowActive = 1 THEN '9999-12-31' ELSE case when ( c2.rowno is null ) THEN '9999-12-31' 
                else DATEADD(second, -1, coalesce(c2.FROMDT,'9999-12-31') ) End END
                AS TO_DATE
                from  cte c1   left join cte c2 
                on c1.rowno+1= c2.rowno and c1.COMP1=c2.COMP1

                order by c1.BINGID,DTSEARCH

还要检查Demo