带有 PARTITION BY 和 ORDER BY 的 OVER 子句可忽略主查询的 WHERE 子句

问题描述 投票:0回答:1

假设我们有以下数据表,我临时生成并填充到下面的 SQL 查询中。我想要的是找到给定名称的第一个循环记录,忽略末尾的 where 子句。日期戳顺序后面有一个“周期”列。请注意,每个名称的周期编号不一定从 1 开始。因此,对于每个名称,我想根据日期戳和周期编号了解哪条记录代表第一个周期,因为具有相同时间戳的多个记录可能具有不同的周期编号;在这种情况下,最早的记录是循环数较低的记录。

CREATE TABLE temp_table (
    Id INT,
    Cycle INT,
    DateStamp DateTime2,
    Name VARCHAR(255)
);

INSERT INTO temp_table (id, Cycle, DateStamp, Name)
VALUES  (1, 4, '2024-01-10T17:53:12', 'John'),
        (2, 5, '2024-01-10T17:53:14', 'John'),
        (3, 3, '2024-01-10T17:53:10', 'John'),
        (4, 7, '2024-01-10T17:53:14', 'John'),
        (5, 2, '2024-01-10T17:53:10', 'John'),
        (6, 2, '2024-01-10T17:53:11', 'George'),
        (7, 1, '2024-01-10T17:53:11', 'George'),
        (8, 4, '2024-01-10T17:53:13', 'George'),
        (9, 3, '2024-01-10T17:53:12', 'George'),
       (10, 7, '2024-01-10T17:53:11', 'Tom'),
       (11, 4, '2024-01-10T17:53:10', 'Tom'),
       (12, 8, '2024-01-10T17:53:12', 'Tom'),
       (13, 3, '2024-01-10T17:53:10', 'Tom'),
       (14, 5, '2024-01-10T17:53:11', 'Tom'),
       (15, 6, '2024-01-10T17:53:11', 'Tom'),
       (16, 9, '2024-01-10T17:53:12', 'Tom');
       
SELECT * FROM temp_table;

SELECT *,
      CASE WHEN FIRST_VALUE(Id) OVER (PARTITION BY Name ORDER BY DateStamp, Cycle) = Id THEN 1 ELSE 0 END AS IsFirstCycle
FROM temp_table
WHERE Name = 'Tom' --AND Id >= 14
DROP TABLE temp_table;

一切正常,上面的查询清楚地表明每个名称分区的哪条记录代表基于日期和周期编号的初始周期。在上面的示例中,我进行了筛选以仅查看 Tom 的最终结果记录。请参阅下面的结果图:

但是,我的问题是,当我取消注释并添加另一个条件以通过记录 ID 超过特定值(上例中的 14)来过滤最终结果时,我仍然会得到一条标记为该子分区的第一个周期的记录。但我所期待和想要看到的是,这个子分区中没有记录是最初的第一个周期,因为对我来说第一个周期记录是整个分区上的记录,忽略整个查询的 WHERE 子句。

据我从互联网上阅读和理解的内容,OVER 子句应该与 WHERE 子句无关。当然,我想在最后通过 WHERE 子句进行过滤,并仅显示 ID 超过任意数量的记录,但是当进行分区时,我需要检测记录是否是第一个循环,我想考虑的不是子集,而是完整表中的完整分区,忽略任何 WHERE 条件。请指导我如何实现这一点,因为 OVER 子句首先根据 ID > 14 条件明确过滤分区记录,然后再应用 OVER 子句来检测和标记该分区内的第一个循环记录。我的期望是返回第二个图像中的三个记录,其中所有记录的 IsFirstCycle 标记为 0,因为 Tom 分区中唯一的第一个循环记录是第一个图像中 Id=13 的记录。

sql over-clause
1个回答
0
投票

您可以使用子选择来获取一个(或多个)用户的最低 ID

SELECT *,
      CASE WHEN (SELECT MIN(id) FROM temp_table WHERE Name = t2.Name) = Id THEN 1 ELSE 0 END AS IsFirstCycle
FROM temp_table t2
WHERE Name = 'Tom' 
  AND Id >= 14

身份证 循环 日期戳 姓名 是第一个周期
14 5 2024-01-10 17:53:11 汤姆 0
15 6 2024-01-10 17:53:11 汤姆 0
16 9 2024-01-10 17:53:12 汤姆 0
© www.soinside.com 2019 - 2024. All rights reserved.