我在从表中显示正确的数据时遇到了一些麻烦。 我不确定要搜索什么。 我不确定min(列)或max(列)会在这里帮助我。让我们看看我是否可以解释我的问题。
我的表格包含以下数据:
> Code (nvarchar) | DateFrom (datetime) | DateTo (datetime)
> =========================================================
> 3006 | 2014-06-18 07:00:00 | 2014-06-18 08:00:00
> 3006 | 2014-06-18 09:00:00 | 2014-06-18 22:00:00
> 1006 | 2014-06-18 07:00:00 | 2014-06-18 09:00:00
> 1006 | 2014-06-18 08:00:00 | 2014-06-18 08:30:00
> 1006 | 2014-06-18 08:10:00 | 2014-06-18 18:00:00
我将以一种观点来呈现这一点。 它将按代码分组。
我想要的是这个输出:
> Code | DateFrom | DateTo
> =========================================================
> 3006 | 2014-06-08 07:00:00 | 2014-06-18 08:00:00
> 3006 | 2014-06-18 09:00:00 | 2014-06-18 22:00:00
> 1006 | 2014-06-18 07:00:00 | 2014-06-18 18:00:00
如果您看到DateTo和DateFrom之间是否存在空白,我希望它显示为两行。但是如果具有相同代码的下一个“DateFrom”在DateTo结束之前(或同时)开始,我希望改为显示“DateTo”。
在这种情况下,我看不出如何使用函数max()或min()。因为在时间段期间可能存在间隙。
你们有什么线索吗?
我正在使用MS SQL 2012
提前致谢!
编辑:评论。群岛可能是我的解决方案吗?
答案 0 :(得分:5)
旧的答案有一个缺点:每行都只检查前一个,以验证周期是否重叠,如果前一行的周期超过逻辑不会考虑它。例如:
Code | DateStart | DateFrom | Overlap
-----+---------------------+---------------------+---------
1006 | 2014-06-18 07:00:00 | 2014-06-18 19:00:00 | 0
1006 | 2014-06-18 08:10:00 | 2014-06-18 10:00:00 | 1
1006 | 2014-06-18 16:00:00 | 2014-06-18 20:30:00 | 0 <- don't overlap with
previous but overlap
with the first
要改善PrevStop
需要成为LastStop
,并且DateFrom
Code
的最大值
With N AS (
SELECT Code, DateFrom, DateTo
, LastStop = MAX(DateTo)
OVER (PARTITION BY Code ORDER BY DateFrom, DateTo
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
FROM Table1
), B AS (
SELECT Code, DateFrom, DateTo
, Block = SUM(CASE WHEN LastStop Is Null Then 1
WHEN LastStop < DateFrom Then 1
ELSE 0
END)
OVER (PARTITION BY Code ORDER BY DateFrom, LastStop)
FROM N
)
SELECT Code
, MIN(DateFrom) DateFrom
, MAX(DateTo) DateTo
FROM B
GROUP BY Code, Block
ORDER BY Code, Block
需要 ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
才能从MAX
删除当前行。
旧答案
此查询仅适用于每个句点并非完全在先例内。
这个想法是检查每一行是否与下一个/上一个链接
如果行被链接,则它们形成一个块,它们将被组合在一起以获得第一个DateFrom
和最后一个DateTo
With N AS (
SELECT Code, DateFrom, DateTo
, PrevStop = LAG(DateTo, 1, NULL)
OVER (PARTITION BY Code ORDER BY DateFrom)
FROM Table1
), B AS (
SELECT Code, DateFrom, DateTo
, Block = SUM(CASE WHEN PrevStop Is Null Then 1
WHEN PrevStop < DateFrom Then 1
ELSE 0
END)
OVER (PARTITION BY Code ORDER BY PrevStop)
FROM N
)
SELECT Code
, MIN(DateFrom) DateFrom
, MAX(DateTo) DateTo
FROM B
GROUP BY Code, Block
ORDER BY Code, Block
SQLFiddle demo 添加了一些数据以在同一代码/日检查更多块
查询搜索块启动器检查每一行,如果它们是代码的第一行(PrevStop IS NULL
),或者它们是否在前一行(PrevStop < DateFrom
之外)。
窗口SUM
仅检索ORDER
的上一行,以便为链接数据块创建常量值,例如,我们将获得测试数据
Code | DateStart | DateFrom | Starter | Block
-----+---------------------+---------------------+---------+------
1006 | 2014-06-18 07:00:00 | 2014-06-18 09:00:00 | 1 | 1
1006 | 2014-06-18 08:10:00 | 2014-06-18 06:00:00 | 0 | 1
1006 | 2014-06-18 08:00:00 | 2014-06-18 08:30:00 | 0 | 1
1006 | 2014-06-18 07:00:00 | 2014-06-18 07:30:00 | 1 | 2
1006 | 2014-06-18 08:00:00 | 2014-06-18 08:30:00 | 1 | 3
1006 | 2014-06-18 08:10:00 | 2014-06-18 09:00:00 | 0 | 3
3006 | 2014-06-18 07:00:00 | 2014-06-18 08:00:00 | 1 | 1
3006 | 2014-06-18 09:00:00 | 2014-06-18 10:00:00 | 1 | 2
按Code
和Block
分组获得结果