然而,在Get top 1 row of each group的情况下也提出了类似的问题,在这种情况下,没有WHERE条件改变预期输出.所以我的案子是这样的.

假设我们有以下数据表,我在下面的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的最终结果记录.

查看结果的屏幕截图:

enter image description here

然而,我的问题是,当我取消注释并添加另一个条件以按记录ID筛选最终结果时(在上面的示例中为14),我仍然得到一个被标记为该子分区的第一个周期的记录.

但我期望也希望看到的是,该子分区中没有记录是初始的第一个周期,因为我的第一个周期记录是整个分区上的记录,忽略了整个查询的WHERE子句.

enter image description here

据我在网上的阅读和理解,以上条款应该是WHERE条款不可知的.当然,我希望在最后按WHERE子句进行筛选,并且只显示ID超过任何数字的记录,但是当我需要检测记录是否是第一个周期时,我不想考虑子集,而是考虑整个表中的完整分区,而忽略任何WHERE条件.请指导我如何实现这一点,因为OVER子句清楚地首先根据ID&>14条件过滤分区记录,然后应用OVER子句来检测和标记该分区内的第一个周期记录.我的预期是返回第二个图像中的三个记录,其中所有记录的IsFirstCycle都被标记为0,因为Tom分区中唯一的第一个周期记录是ID=13的记录,如第一个屏幕截图所示.

推荐答案

您可以使用子 Select 来获取一个(或多个)用户的最低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

Id Cycle DateStamp Name IsFirstCycle
14 5 2024-01-10 17:53:11 Tom 0
15 6 2024-01-10 17:53:11 Tom 0
16 9 2024-01-10 17:53:12 Tom 0

您可以将内部SELECT更改为可以更好地排序的内容

喜欢

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

此外,您还可以使用带有rownumber的CTE作为进一步的可能性.

由于您的实际情况比较复杂,但我们对此一无所知,您必须添加另一个表,并手动判断一个用户是否 Select 了正确的ID,否则您必须细化您的分配

Sql相关问答推荐

JSON列之间的Postgr聚合

在Postgres中实现合并功能的干净方法,因为当目标/源不匹配时

从日期开始向前填充重复项

编写一个SQL查询来返回收视率较高的类型,并取这些收视率的平均值,我该如何做呢?

通过之前的连接-这是Oracle的错误吗?

基于唯一值在Access查询中创建计数器

为什么我的SQL标量函数有时会抛出";子查询返回多个值.这是不允许的.

带上最后日期(结果)

ColdFusion+Docker:未安装SQLSERVER包

将JSON文件导入Postgres 16数据库时出错(22P04上次预期列之后的额外数据)

根据时间、状态和相关行在PostgreSQL中的存在来删除行

在 PostgreSQL 中使用 ltree 列进行累积

在 PostgreSQL 中生成时间序列查询

Postgresql - 如何根据阈值计算累积和

MariaDB非常简单的MATCHAGAINST查询不使用FULLTEXT索引吗?

Postgres数据库维护:基于GROUP BY删除旧记录

SQL 计数和过滤查询优化

如何根据 ID 和指标从 2 个表中找到不同的值?

ACCESS SQL - 有没有办法使用通配符仅 Select 字段的特定部分?

SQL中所有先前日期的累计总和