简体   繁体   English

SQL查找首次出现

[英]SQL Find First Occurrence

I've been at this for about an hour now and am making little to no progress - thought I'd come here for some help/advice. 我已经在这里待了大约一个小时,而且几乎没有任何进展 - 我以为我会来这里寻求帮助/建议。

So, given a sample of my table: 所以,给出我的表样本:

+-----------+-----------------------------+--------------+
| MachineID | DateTime                    | AlertType    |
+-----------+-----------------------------+--------------+
| 56        | 2015-10-05 00:00:23.0000000 | 2000         |
| 42        | 2015-10-05 00:01:26.0000000 | 1006         |
| 50        | 2015-10-05 00:08:33.0000000 | 1018         |
| 56        | 2015-10-05 00:08:48.0000000 | 2003         |
| 56        | 2015-10-05 00:10:15.0000000 | 2000         |
| 67        | 2015-10-05 00:11:59.0000000 | 3001         |
| 60        | 2015-10-05 00:13:02.0000000 | 1006         |
| 67        | 2015-10-05 00:13:08.0000000 | 3000         |
| 56        | 2015-10-05 00:13:09.0000000 | 2003         |
| 67        | 2015-10-05 00:14:50.0000000 | 1018         |
| 67        | 2015-10-05 00:15:00.0000000 | 1018         |
| 47        | 2015-10-05 00:16:55.0000000 | 1006         |
+-----------+-----------------------------+--------------+

How would I get the first occurrence of MachineID w/ an AlertType of 2000 and the last occurrence of the same MachineID w/ and AlertType of 2003. 我将如何得到第一次出现MachineID瓦特/一AlertType 2000和相同的最后一次出现MachineID瓦特/和AlertType 2003。

Here is what I have tried - but it is not outputting what I expect. 这是我尝试过的 - 但它没有输出我的期望。

SELECT *
FROM [Alerts] a
where 
    DateTime >= '2015-10-05 00:00:00'
    AND  DateTime <= '2015-10-06 00:00:00'
    and not exists(
        select b.MachineID 
        from [Alerts] b
        where   b.AlertType=a.AlertType and
                b.MachineID<a.MachineID
    )
order by a.DateTime ASC

EDIT: The above code doesn't get me what I want because I am not specifically telling it to search for AlertType = 2000 or AlertType = 2003 , but even when I try that, I am still unable to gather my desired results. 编辑: 上面的代码没有得到我想要的东西因为我没有具体告诉它搜索AlertType = 2000AlertType = 2003 ,但即使我尝试了,我仍然无法收集我想要的结果。

Here is what I would like my output to display: 这是我想要显示的输出:

+-----------+-----------------------------+--------------+
| MachineID | DateTime                    | AlertType    |
+-----------+-----------------------------+--------------+
| 56        | 2015-10-05 00:00:23.0000000 | 2000         |
| 56        | 2015-10-05 00:13:09.0000000 | 2003         |
+-----------+-----------------------------+--------------+

Any help with this would be greatly appreciated! 任何有关这方面的帮助将不胜感激!

Not sure, but: 不确定,但是:

select * from [Table] 
WHERE [DateTime] IN (
            SELECT MIN([DateTime]) as [DateTime] 
            FROM [Table] 
            WHERE AlertType = 2000 
            GROUP BY MachineId 
                UNION ALL 
            SELECT MAX([DateTime]) as [DateTime] 
            FROM [Table] 
            WHERE AlertType = 2003 
            GROUP BY MachineId)
ORDER BY MachineId, AlertType

It looks like your outer section takes all records between 2015-10-05 to 2015-10-06, which includes all the records sorted by date. 您的外部部分看起来像2015-10-05到2015-10-06之间的所有记录,其中包括按日期排序的所有记录。 The inner portion only happens when no records fit the outer date range. 内部部分仅在没有记录符合外部日期范围时发生。

Looks like GSazheniuk has it right, but I am not sure if you just want the 2 records or everything that matches the MachineID and the two alerts? 看起来像GSazheniuk它是正确的,但我不确定你是否只想要2条记录或所有匹配MachineID和两个警报?

Not sure what your attempt has to do with your question, but to answer this: 不确定您的尝试与您的问题有什么关系,但要回答这个问题:

How would I get the first occurrence of MachineID w/ an AlertType of 2000 and the last occurrence of the same MachineID w/ and AlertType of 2003. 如何首次出现具有2000的AlertType和最后一次出现的相同MachineID w /和AlertType为2003的MachineID。

Simple: 简单:

SELECT * FROM (
    SELECT TOP 1 * FROM Alerts WHERE AlertType='2000' ORDER BY Datetime ASC
    UNION ALL 
    SELECT TOP 1 * FROM Alerts WHERE AlertType='2003' ORDER BY Datetime DESC
) t

I think everyone misses that your alert type is NOT a deciding factor, but a supplemental. 我想每个人都错过了你的警报类型不是决定因素,而是一个补充。 This should give you what you are looking for. 这应该可以满足您的需求。 I walked through the whole process. 我走过了整个过程。 `IF OBJECT_ID('tempdb..#alerts') IS NOT NULL DROP table #alerts `IF OBJECT_ID('tempdb ..#alerts')IS NOT NULL DROP表#alerts

    CREATE TABLE #alerts
    (
    MachineID int,
    dte DATETIME,
    alerttype int
    )
INSERT INTO #alerts VALUES ('56','20151005 00:00:23','2000')
INSERT INTO #alerts VALUES ('42','20151005 00:01:26','1006')
INSERT INTO #alerts VALUES ('50','20151005 00:08:33','1018')
INSERT INTO #alerts VALUES ('56','20151005 00:08:48','2003')
INSERT INTO #alerts VALUES ('56','20151005 00:10:15','2000')
INSERT INTO #alerts VALUES ('67','20151005 00:11:59','3001')
INSERT INTO #alerts VALUES ('60','20151005 00:13:02','1006')
INSERT INTO #alerts VALUES ('67','20151005 00:13:08','3000')
INSERT INTO #alerts VALUES ('56','20151005 00:13:09','2003')
INSERT INTO #alerts VALUES ('67','20151005 00:14:50','1018')
INSERT INTO #alerts VALUES ('67','20151005 00:15:00','1018')
INSERT INTO #alerts VALUES ('47','20151005 00:16:55','1006')
GO
WITH rnk as ( --identifies the order of the records. 
    Select 
        MachineID,
        dte = dte,
        rnk = RANK() OVER (partition BY machineid ORDER BY dte DESC) --ranks the machine ID's based on date (first to Last)
        FROM #alerts
        ),
    agg  as( --Pulls your first  and last record
    SELECT 
        MachineID,
        frst = MIN(rnk), 
        lst = MAX(rnk) 
    FROM rnk 
    GROUP BY MachineID
    )
SELECT
    pop.MachineID,
    pop.dte,
    pop.alerttype

FROM #alerts pop
JOIN rnk r ON pop.MachineID = r.MachineID AND pop.dte = r.dte --the date join allows you to hook into your ranks
JOIN agg ON pop.MachineID = agg.MachineID 
WHERE agg.frst = r.rnk OR agg.lst = r.rnk -- or clause can be replaced by two queries with a union all
ORDER BY 1,2 --viewability... machineID, date`

I personally use cross apply's to preform tasks like this, but CTE's are much more visually friendly for this exercise. 我个人使用交叉应用来执行这样的任务,但是CTE对于这个练习来说更具视觉友好性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM