如何在不使用 HAVING 子句的情况下仅 select 不相关的行

How to select only not related rows without using HAVING clause

我有 table 个“连续剧”,数据如下:

Serial Date Status
A00010 03.03.2022 BAD
A00010 04.03.2022 GOOD
A00011 05.03.2022 BAD
A00012 06.03.2022 BAD

我只想select那些实际状态不好的序列号。 所以结果我只期望 A00011 和 A00012。这是因为 A00010 最新(查看日期)状态为 GOOD。 查询应该 return 只有 DISTINCT 值(这里我使用序列号分组)。

我找到的唯一解决方案是使用 HAVING 子句:

SELECT [Serial], MAX([Date]),  MAX([Status])
FROM [Serials]
GROUP BY [Serial]
HAVING MAX([Status]) != 'GOOD'

我宁愿避免使用它,因为它会占用更多资源(特别是扫描更大的 table 时)。此外,无论如何,table 中的大多数连续出版物的最新记录都是 GOOD,因此当前查询将提取几乎整个 table,然后 HAVING 将只裁剪其中的大部分。对于 big table 这将是资源的巨大浪费。 因此,如果有人可以帮助我找到将执行相同但仅使用 WHERE 子句的查询。 谢谢

一种选择是使用 ROW_NUMBER() 查找每个序列号的最后一行,然后过滤掉状态良好的那些行。

WITH
  sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY Serial ORDER BY [date] DESC)   AS serial_row   
  FROM
    serials
)
SELECT
  *
FROM
  sorted
WHERE
      serial_row  = 1
  AND status     != 'GOOD'

试试这个:

Select Serial
From Serials s
Where s.Date = 
   (Select Max(Date) From Serials
        Where Serial = s.Serial) 
   And Status != 'Good'

如果 table 中可以存在多个相同 Serial 和 Date 的记录,则添加 Distinct

Select Distinct Serial
From Serials s
Where s.Date = 
    (Select Max(Date) From Serials
        Where Serial = s.Serial) 
   And Status != 'Good'

为了在第三条评论中也解决您的请求,(仅针对 select 以前很好的连续剧),只需将其作为附加谓词添加到 Where 子句中:

Select Distinct Serial
From Serials s
Where s.Date = 
    (Select Max(Date) From Serials
        Where Serial = s.Serial) 
   And Status != 'Good'
   And exists                  -- This predicate ensures that only 
      (Select * from Serial x   -- previously 'GOOD' serials 
       Where serial = s.Serial  -- will appear
          and Date < (Select Max(Date) From Serials
                      Where Serial = s.Serial) 
          and status = 'GOOD')                        

基本上你想做的可以直接翻译成SQL:

您想要一个 [distinct] 列表,这些序列是每个特定序列的最后一个按时间顺序排列的记录的集合,过滤为仅包括不好的。 因此,您创建了一个子 table,它只包含日期是该序列的最新日期的记录,然后按状态过滤它以仅包含不好的记录,然后从中提取序列值 table.

根据 table 的大小,如果您在 Date 属性上有索引,这将非常有效(或更好)。