查询从日期时间列表中提取句点

时间:2016-03-30 21:00:42

标签: sql sql-server tsql

我一直很难在SQL Server 2012上进行查询,以便在下面提取这些数据,这样我就可以得到我想要的输出。

基本上我只有下面的Logs表,它是一个打开和关闭日期的列表。

输入数据,按ItemID和SystemDate DESC排序:

ItemID | StartDate               | EndDate                 | SystemDate

1134   | 2007-01-18 08:56:14.000 | 2007-05-16 17:54:44.700 | 2011-12-12 12:19:23.647
1134   | 2007-01-18 08:56:14.000 | 2007-05-16 17:54:44.700 | 2007-05-16 17:54:44.700
1134   | 2007-01-18 08:56:14.000 | NULL                    | 2007-03-06 10:18:50.567
1134   | 2007-01-18 08:56:14.000 | 2007-03-02 11:21:12.057 | 2007-03-02 11:21:12.057 
1134   | 2007-01-18 08:56:14.000 | NULL                    | 2007-01-18 09:09:38.597
2468   | 2008-11-24 11:36:20.000 | 2012-11-12 15:40:32.730 | 2012-11-12 15:40:32.730
2468   | 2008-11-24 11:36:20.000 | NULL                    | 2009-02-04 11:05:47.060
2468   | 2008-11-24 11:36:20.000 | NULL                    | 2009-02-04 11:03:16.903
2468   | 2008-11-24 11:36:20.000 | 2009-02-04 10:41:05.590 | 2009-02-04 10:41:05.590
2468   | 2008-11-24 11:36:20.000 | NULL                    | 2008-11-25 17:06:53.753
2468   | 2008-11-24 11:36:20.000 | NULL                    | 2008-11-25 17:02:52.020
2468   | 2008-11-24 11:36:20.000 | 2008-11-25 10:50:54.387 | 2008-11-25 10:50:54.417
2468   | 2008-11-24 11:36:20.000 | NULL                    | 2008-11-24 11:39:12.013
2562   | 2009-01-08 16:44:00.000 | NULL                    | 2009-01-08 16:47:07.983
11021  | 2016-03-22 13:44:26.000 | 2016-05-05 00:00:00.000 | 2016-03-22 14:08:01.783

我想要的输出:

ItemID |StartDate                | EndDate                 | SystemDate

1134   | 2007-03-06 10:18:50.567 | 2007-05-16 17:54:44.700 | 2011-12-12 12:19:23.647
1134   | 2007-01-18 08:56:14.000 | 2007-03-02 11:21:12.057 | 2007-03-02 11:21:12.057
2468   | 2009-02-04 11:03:16.903 | 2012-11-12 15:40:32.730 | 2012-11-12 15:40:32.730
2468   | 2008-11-25 17:02:52.020 | 2009-02-04 10:41:05.590 | 2009-02-04 10:41:05.590
2468   | 2008-11-24 11:36:20.000 | 2008-11-25 10:50:54.387 | 2008-11-25 10:50:54.417
2562   | 2009-01-08 16:44:00.000 | NULL                    | 2009-01-08 16:47:07.983
11021  | 2016-03-22 13:44:26.000 | 2016-05-05 00:00:00.000 | 2016-03-22 14:08:01.783

ItemID 1134的简要示例:

1134   | 2007-01-18 08:56:14.000 | 2007-05-16 17:54:44.700 | 2011-12-12 12:19:23.647  (period still closed, some modification on other data)
1134   | 2007-01-18 08:56:14.000 | 2007-05-16 17:54:44.700 | 2007-05-16 17:54:44.700 (period closed again)
1134   | 2007-01-18 08:56:14.000 | NULL                    | 2007-03-06 10:18:50.567 (period reopened)
1134   | 2007-01-18 08:56:14.000 | 2007-03-02 11:21:12.057 | 2007-03-02 11:21:12.057 (period closed)
1134   | 2007-01-18 08:56:14.000 | NULL                    | 2007-01-18 09:09:38.597  (period opened for the first time, no end date)

项目2468的示例,我希望能更好地解释我想要的输出

Example of item 2468, hope it clears up the idea

非常感谢您的任何帮助或提示。

编辑(遵循发布SQL问题的指南)

DROP TABLE mytable;

CREATE TABLE mytable(
   ItemID     INTEGER  NOT NULL
  ,StartDate  DATETIME  NOT NULL
  ,EndDate    DATETIME  NOT NULL
  ,SystemDate DATETIME  NOT NULL
);
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000','2007-05-16 17:54:44.700','2011-12-12 12:19:23.647');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000','2007-05-16 17:54:44.700','2007-05-16 17:54:44.700');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000',NULL,'2007-03-06 11:07:44.413');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000',NULL,'2007-03-06 10:19:24.160');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000',NULL,'2007-03-06 10:18:50.567');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000','2007-03-02 11:21:12.057','2007-03-02 11:21:12.057');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (1134,'2007-01-18 08:56:14.000',NULL,'2007-01-18 09:09:38.597');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000','2012-11-12 15:40:32.730','2012-11-12 15:40:32.730');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000',NULL,'2009-02-04 11:05:47.060');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000',NULL,'2009-02-04 11:03:16.903');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000','2009-02-04 10:41:05.590','2009-02-04 10:41:05.590');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000',NULL,'2008-11-25 17:06:53.753');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000',NULL,'2008-11-25 17:02:52.020');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000','2008-11-25 10:50:54.387','2008-11-25 10:50:54.417');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2468,'2008-11-24 11:36:20.000',NULL,'2008-11-24 11:39:12.013');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (2562,'2009-01-08 16:44:00.000',NULL,'2009-01-08 16:47:07.983');
INSERT INTO mytable(ItemID,StartDate,EndDate,SystemDate) VALUES (11021,'2016-03-22 13:44:26.000','2016-05-05 00:00:00.000','2016-03-22 14:08:01.783');

OUTPUT想要

+--------+-------------------------+-------------------------+-------------------------+
| ItemID | StartDate               | EndDate                 | ModificationDate        |
+--------+-------------------------+-------------------------+-------------------------+
| 1134   | 2007-03-06 10:18:50.567 | 2007-05-16 17:54:44.700 | 2011-12-12 12:19:23.647 |
| 1134   | 2007-01-18 08:56:14.000 | 2007-03-02 11:21:12.057 | 2007-03-02 11:21:12.057 |
| 2468   | 2009-02-04 11:03:16.903 | 2012-11-12 15:40:32.730 | 2012-11-12 15:40:32.730 |
| 2468   | 2008-11-25 17:02:52.020 | 2009-02-04 10:41:05.590 | 2009-02-04 10:41:05.590 |
| 2468   | 2008-11-24 11:36:20.000 | 2008-11-25 10:50:54.387 | 2008-11-25 10:50:54.417 |
| 2562   | 2009-01-08 16:44:00.000 | NULL                    | 2009-01-08 16:47:07.983 |
| 11021  | 2016-03-22 13:44:26.000 | 2016-05-05 00:00:00.000 | 2016-03-22 14:08:01.783 |
+--------+-------------------------+-------------------------+-------------------------+

1 个答案:

答案 0 :(得分:1)

我认为此查询可以满足您的需求:

WITH cteEventIx AS (
  SELECT e.ItemID, e.StartDate, e.EndDate, e.SystemDate, ROW_NUMBER() OVER (PARTITION BY e.ItemID ORDER BY e.SystemDate ASC) aix, ROW_NUMBER() OVER (PARTITION BY e.ItemID ORDER BY e.SystemDate DESC) dix
  FROM tblEvent e
), cteEventEnd AS (
  SELECT e.ItemID, e.StartDate, e.EndDate, e.SystemDate, e.aix, e.dix
  FROM cteEventIx e
  WHERE e.aix=1
  UNION ALL
  SELECT e.ItemID, CASE WHEN r.EndDate IS NOT NULL AND (e.EndDate IS NULL OR e.EndDate<>r.EndDate) THEN e.SystemDate ELSE r.StartDate END, e.EndDate, e.SystemDate, e.aix, e.dix
  FROM cteEventIx e
  JOIN cteEventEnd r ON e.aix=r.aix+1 AND e.ItemID=r.ItemID
)
SELECT e.ItemID, e.StartDate, e.EndDate, MAX(e.SystemDate) SystemDate
  FROM cteEventEnd e
  WHERE e.EndDate IS NOT NULL OR e.dix=1
  GROUP BY e.ItemID, e.StartDate, e.EndDate
  ORDER BY e.ItemID ASC, e.StartDate DESC
  OPTION (MAXRECURSION 0);

当您使用您提供的测试数据时,结果如下:

| ItemID |               StartDate |                 EndDate |              SystemDate |
|--------|-------------------------|-------------------------|-------------------------|
|   1134 | 2007-03-06 10:18:50.567 | 2007-05-16 17:54:44.700 | 2011-12-12 12:19:23.647 |
|   1134 | 2007-01-18 08:56:14.000 | 2007-03-02 11:21:12.057 | 2007-03-02 11:21:12.057 |
|   2468 | 2009-02-04 11:03:16.903 | 2012-11-12 15:40:32.730 | 2012-11-12 15:40:32.730 |
|   2468 | 2008-11-25 17:02:52.020 | 2009-02-04 10:41:05.590 | 2009-02-04 10:41:05.590 |
|   2468 | 2008-11-24 11:36:20.000 | 2008-11-25 10:50:54.387 | 2008-11-25 10:50:54.417 |
|   2562 | 2009-01-08 16:44:00.000 |                  (null) | 2009-01-08 16:47:07.983 |
|  11021 | 2016-03-22 13:44:26.000 | 2016-05-05 00:00:00.000 | 2016-03-22 14:08:01.783 |

SQL Fiddle