如何在不使用 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 属性上有索引,这将非常有效(或更好)。
我有 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 属性上有索引,这将非常有效(或更好)。