簡體   English   中英

Select 在 SQL 中最后一次出現其他值之后的第一次出現值

[英]Select first occurrence of value after last occurrence of other value in SQL

我需要找到零件的當前操作。 我必須從完成(1)或0的操作狀態列表中獲取此信息的表。因此該表通常如下所示:

ID  Operation  Status

 1      100      1
 2      200      1
 3      250      1
 4      300      0
 5      350      0

所以在這種情況下,操作 300 是我使用 MIN(Operation) WHERE Status = 0 獲得的當前操作。

但是,出現了一些跳過某些操作的情況,如下所示:

ID  Operation  Status

 1     100       1
 2     200       0
 3     250       1
 4     300       0
 5     350       0

所以在這種情況下,當前操作仍然是 Operation 300,但 MIN(Operation) 不起作用。 我需要的是在最后一次出現 Status = 1 行之后出現 Status = 0 的行。 我怎么能做到這一點?

編輯:還必須考慮所有操作都是狀態 0 的情況,其中正確的結果將是第一行(操作 100)

我敢肯定有一個聰明的 window function 方法來做到這一點,但在香草 sql 這就是想法

SELECT MIN(Operation)
  FROM SOME_TABLE
 WHERE Operation > 
         ( SELECT MAX(Operation)
             FROM SOME_TABLE
            WHERE status = 1
         )

這將為您提供整行:

DECLARE @MyTable TABLE (
    ID INT,
    Operation INT,
    Status BIT
);

INSERT INTO @MyTable VALUES
     (1, 100, 1)
    ,(2, 200, 0)
    ,(3, 250, 1)
    ,(4, 300, 0)
    ,(5, 350, 0)
;

WITH MaxOperation AS (
    SELECT MAX(x.Operation) AS MaxOperation
    FROM @MyTable x
    WHERE x.Status = 1
)
SELECT TOP 1 t.*
FROM @MyTable t
    CROSS APPLY (SELECT MaxOperation FROM MaxOperation) x
WHERE t.Operation > x.MaxOperation
    OR x.MaxOperation IS NULL
ORDER BY t.Operation

這將導致:

ID          Operation   Status
----------- ----------- ------
4           300         0

如果所有的Status值都是0 ,它也會產生這個:

ID          Operation   Status
----------- ----------- ------
1           100         0

正如用戶 Error_2646 所指出的,一個好的方法是

select
    min(ID)
from
    [YourTable]
where
    ID > (select max(ID) from [YourTable] where Status = 1)

我希望這個答案能給你正確的答案。 如果您可以在圖像中添加預期的 output,則更容易識別您需要什么。 請在時添加架構和數據,以便用戶放置他們的解決方案。

Schema and data I used:
( 
 ID INT 
 ,operation INT
 ,Status INT 
 )

 insert into  Occurances values(1,100,1)
 insert into  Occurances values(2,200,0)
 insert into  Occurances values(1,250,1)
 insert into  Occurances values(1,300,0)
 insert into  Occurances values(1,350,0)

 SELECT *
 FROM
 (
    SELECT 
    Rank() OVER ( ORDER BY  operation) AS [rank]
    ,MIN([operation]) AS  [min] 
    ,id
    ,[status]
 FROM Occurances
 WHERE [Status]= 0
 GROUP BY  id
    ,[status]
    ,operation
 UNION  
  SELECT 
    Rank() OVER ( ORDER BY  operation DESC) AS [rank]
   ,MAX([operation]) AS  [min] 
   ,id
   ,[status]
 FROM Occurances
 WHERE [Status]= 1
 GROUP BY  id
      ,[status]
      ,operation

 ) AS A
 WHERE A.[rank]= 1

這是我得到的答案:
結果

您可以使用 window function 非常有效地做到這一點:

SELECT TOP (1) *
FROM (
    SELECT *, LEAD(Status) OVER (ORDER BY Operation DESC) AS PreviousStatus
    FROM myTable
)
WHERE Status = 0 AND PreviousStatus = 1
ORDER BY Operation DESC

嘗試這個:

DECLARE @Table TABLE
        (
                ID          int
            ,   Operation   int
            ,   [Status]    bit
        )
;

INSERT INTO @Table (ID, Operation,  [Status])
    VALUES
                (1, 100, 1)
            ,   (2, 200, 0)
            ,   (3, 250, 1)
            ,   (4, 300, 1)
            ,   (5, 350, 0)
;

SELECT  TOP 1 T.*
FROM    @Table T
WHERE   T.[Status] = 0
    AND T.ID    >   (
                        SELECT  TOP 1 T.ID
                        FROM    @Table  T
                        WHERE   T.[Status] = 1
                        ORDER BY ID DESC
                    )   
ORDER BY    ID

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM