【问题标题】:Count number of previous records using T-SQL使用 T-SQL 计算以前的记录数
【发布时间】:2026-01-17 12:35:02
【问题描述】:

我有一个 SQL 表,我需要在其中获取带有日期的最后一行的数字,并计算之前的行数,即使它们都没有日期。

例如

02/01/2011
03/01/2011
09/01/2011
NULL
10/10/2011
NULL

此表应返回第 5 条记录的数字 5

NULL
NULL
NULL
09/01/2011
NULL
10/10/2011
NULL

这个表应该返回 6

提前谢谢你

J

----- 更新 ------ 更多信息

该表本身代表完成的工作单元(里程碑),并链接到代表工作单元的父表。在里程碑表中,它包含日期、父工作 ID 和里程碑 ID。

从第一个例子开始

ParentID    MilestoneID    Date
1234        123            02/01/2011
1234        124            03/01/2011
1234        125            09/01/2011
1234        126            NULL
1234        127            10/10/2011
1234        128            NULL

希望对你有帮助

----- 更新 2 -----

我得到的最接近的是这个

SELECT TOP 1
    Num
FROM
    (
    SELECT
        ROW_NUMBER()OVER(ORDER BY ParentID) AS Num,
        Date

    FROM
        Milestone
    WHERE
        Milestone.ParentID = 1234
) AS MilestoneStones

在哪里 日期不为空 订购方式 数字 DESC

但是由于数据集很大并且附加了其他东西,它变得非常慢 希望我能得到更好的东西

谢谢

J

【问题讨论】:

  • 最后一行真的需要在这个查询中吗?你能不能在处理查询结果的代码中得到计数,不管是什么。
  • 什么决定了该字段可以为 NULL 的行的顺序?有 ID 列吗?
  • ROW_NUMBER()OVER(ORDER BY ParentID) AS Num 应该是 ROW_NUMBER()OVER(ORDER BY ParentID, MilestoneID) AS Num 或者只是 ROW_NUMBER()OVER(ORDER BY MilestoneID) AS Num跨度>

标签: sql-server tsql count


【解决方案1】:

我将假设一些名为 ord 的排序列和一个名为 dt 的日期列:

天真地:

SELECT COUNT(*)
FROM tbl
WHERE ord <= (SELECT MAX(ord) FROM tbl WHERE dt IS NOT NULL)

使用更新后的数据,看看效果如何:

https://data.stackexchange.com/*/q/109223/

DECLARE @tbl AS TABLE (ParentID INT, MilestoneID INT, [Date] DATETIME);
INSERT INTO @tbl VALUES (1234,        123,            '02/01/2011');
INSERT INTO @tbl VALUES (1234,        124,            '03/01/2011');
INSERT INTO @tbl VALUES (1234,        125,            '09/01/2011');
INSERT INTO @tbl VALUES (1234,        126,            NULL);
INSERT INTO @tbl VALUES (1234,        127,            '10/10/2011');
INSERT INTO @tbl VALUES (1234,        128,            NULL);

WITH LastCompleted AS (
    SELECT ParentID, MAX(MilestoneID) AS MAXMilestoneID
    FROM @tbl AS Milestone
    WHERE [Date] IS NOT NULL
    GROUP BY ParentID
)
SELECT LastCompleted.ParentID, COUNT(*) AS NumMilestones
FROM LastCompleted
INNER JOIN @tbl AS Milestone
    ON LastCompleted.ParentID = Milestone.ParentID
    AND LastCompleted.MAXMilestoneID >= Milestone.MilestoneID
GROUP BY LastCompleted.ParentID;

【讨论】:

  • 我认为他需要的是 ROWNUMBER 而不是伯爵 - 或者伯爵会给他那个?
  • @Jack Marchetti 他们会是一样的。这是简单和便携的。有更巧妙的方法来做到这一点。
  • 我已经尝试过这个(或非常相似的东西),但它给我的第一个例子是 4 而不是 5。
  • 需要在Ord By ord末尾添加如下一行
  • @BalamBalam 没必要。在这个例子中,MAX 是一个完整的集合。
【解决方案2】:

我不确定您隐含的排序顺序是什么。是输入项目的顺序吗?如果是这样,请尝试添加身份字段。它将随着您添加的每一行而递增。要计算特定行的行号,只需对标识字段小于或等于目标行的记录进行计数即可。

如果您打算使用其他排序顺序,则从您的示例中不清楚。

【讨论】:

    【解决方案3】:

    需要有一个 Order by,你的自然排序是 ParentID、MilestoneID,而且语法比你想象的要复杂。如果没有 Order By 子句,则无法保证排序(即使表具有集群 PK)。凯德,我喜欢你的回答,我勾选了它,但我无法在评论中发布代码示例。

        SELECT COUNT(*)
        FROM tbl
        WHERE ParentID <= (SELECT MAX(ParentID) FROM tbl WHERE dt IS NOT NULL) 
        Or ( ParentID = (SELECT MAX(ParentID) FROM tbl WHERE dt IS NOT NULL)  
             And MilestoneID <= (Select MAX (MilestoneID) FROM tbl  
                 where ParentID = (SELECT MAX(ParentID) FROM tbl WHERE dt IS NOT NULL)
                 And dt IS NOT NULL)
            )
        Order By ParentID, MilestoneID
    

    我知道简化这一点很容易,但我做了很多多列排序,我需要抓取接下来的 X 行,并且有一些微妙的方法可以被烧毁。对于您的简单计数,是的,您也许可以简化,但我也认为这会给您正确的答案。

    【讨论】: