SQL选择列基于左连接后另一列的MIN值

时间:2019-11-26 02:03:32

标签: sql sql-server

我有一个表,其中的列如下,让我们将表称为事件:

$slide.Shapes.Item(9).table.cell(1,1).Shape.TextFrame.TextRange.Text

我需要根据每个事件的最近IncidentId, IncidentType, StartDate, EndDateEndDate来找到先前事件的结束日期。因此,作为起点,我编写了如下查询:

EventType

但是我不知道该怎么走。我使用SELECT i1.IncidentId, i2.IncidentId, i2.EndDate, DATEDIFF(DAY, i1.StartDate, i2.EndDate) AS DD FROM Incident i1 LEFT JOIN Incident i2 ON i1.IncidentId != i2.IncidentId AND i1.IncidentType != 3 i2.IncidentType = 1 AND i2.EndDate < i1.StartDate GROUP BY进行嵌套查询,问题是我需要MIN的{​​{1}},但是如果我对ID和EndDate我将以开始时得到结束。

我一天结束时需要做的事情类似于:

EndDate

给出以下示例表:

i2

我希望得到以下结果:

SELECT 
    Incident.*
FROM 
    Incident 
LEFT JOIN 
    <RESULTS> ON Incident.IncidentId = <RESULTS>.IncidentId 
WHERE 
    ISNULL(<RESULTS>.EndDate, Incident.EndDate) > 'Some Random Date'

说明:
每当我们|IncidentId|IncidentType|StartDate | EndDate | |:--------:|:----------:|:--------:|:------i-:| |1 |1 |2019-06-01|2019-07-01| |2 |2 |2019-10-01|2018-11-11| |3 |3 |2019-06-01|2019-06-06| |4 |1 |2019-01-01|2019-04-02| |5 |2 |2019-05-01|2019-05-28| |6 |3 |2019-12-01|2019-12-11| 不是|IncidentId|IncidentType|StartDate | EndDate | Previous Incident EndDate | |:--------:|:----------:|:--------:|:--------:|:-------------------------:| |1 |1 |2019-06-01|2019-07-01| 2019-04-02 | \* EndDate of 4*\ |2 |2 |2019-10-01|2018-11-11| 2019-07-01 | \* EndDate of 1*\ |3 |3 |2019-06-01|2019-06-06| NULL | \* Rule Does not apply to Type 3 *\ |4 |1 |2019-01-01|2019-04-02| NULL | \* First Incident has no EndDate*\ |5 |2 |2019-05-01|2019-05-28| 2019-04-02 | \* EndDate of 4*\ |6 |3 |2019-12-01|2019-12-11| NULL | \* Rule Does not apply to Type 3 *\ 时,如果以前存在这样的EventType,我们都想使用最近的事件EventType 3的{​​{1}}

编辑:我添加了一些示例数据,并扩展了查询范围,以增加查询的深度。

2 个答案:

答案 0 :(得分:1)

最简单的方法是在SQL Server中使用横向联接(CROSS/OUTER APPLY)。

LAG很诱人,但您不仅需要上一行,在某些情况下还需要跳过一些行,因此我不知道如何在这里使用LAG。如果您不需要仅查看带有IncidentType = 1的行,则可以使用LAG

样本数据

DECLARE @T TABLE (IncidentId int NOT NULL PRIMARY KEY, IncidentType int NOT NULL , StartDate date NOT NULL , EndDate date NOT NULL );
INSERT INTO @T VALUES
(1, 1, '2019-06-01', '2019-07-01'),
(2, 2, '2019-10-01', '2018-11-11'),
(3, 3, '2019-06-01', '2019-06-06'),
(4, 1, '2019-01-01', '2019-04-02'),
(5, 2, '2019-05-01', '2019-05-28'),
(6, 3, '2019-12-01', '2019-12-11');

查询

SELECT
    *,
    CASE WHEN IncidentType = 3
    THEN NULL
    ELSE
        A.EndDate
    END AS PreviousIncidentEndDate
FROM
    @T AS T1
    OUTER APPLY
    (
        SELECT TOP(1)
            T2.EndDate
        FROM @T AS T2
        WHERE
            T2.IncidentType = 1
            AND T2.EndDate < T1.StartDate
        ORDER BY T2.EndDate DESC
    ) AS A
ORDER BY
    T1.IncidentId;

结果

+------------+--------------+------------+------------+------------+-------------------------+
| IncidentId | IncidentType | StartDate  |  EndDate   |  EndDate   | PreviousIncidentEndDate |
+------------+--------------+------------+------------+------------+-------------------------+
|          1 |            1 | 2019-06-01 | 2019-07-01 | 2019-04-02 | 2019-04-02              |
|          2 |            2 | 2019-10-01 | 2018-11-11 | 2019-07-01 | 2019-07-01              |
|          3 |            3 | 2019-06-01 | 2019-06-06 | 2019-04-02 | NULL                    |
|          4 |            1 | 2019-01-01 | 2019-04-02 | NULL       | NULL                    |
|          5 |            2 | 2019-05-01 | 2019-05-28 | 2019-04-02 | 2019-04-02              |
|          6 |            3 | 2019-12-01 | 2019-12-11 | 2019-07-01 | NULL                    |
+------------+--------------+------------+------------+------------+-------------------------+

最好在(IncidentType, EndDate)上创建索引。

答案 1 :(得分:0)

  

我需要根据每个事件的最近的上一个EndDate和EventType查找上一个事件的EndDate。

我认为您想要lag()。像这样:

select i.*,
       lag(i.enddate) over (partition by i.eventtype order by i.enddate) as prev_enddate
from incident i