开发者

Count number of previous records using T-SQL

I have a SQL table where I need to get the number for the final row with a date and count the number of previous rows even if they don't have a date in either.

e.g

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

This table should return the number 5 for the 5th record

NULL
NULL
NULL
09/01/2011
N开发者_运维技巧ULL
10/10/2011
NULL

This table should return 6

Thank you in advance

J

----- Update ------ Just a little more information

The table its self represents units of work complete (milestones) and links to a parent table which represents units of work. In the milestone table it contains dates, Parent Work Id and a milsestone ID.

From the first example

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

Hope this helps

----- Update 2 -----

The closest I got was this

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

    FROM
        Milestone
    WHERE
        Milestone.ParentID = 1234
) AS MilestoneStones

WHERE Date IS NOT NULL ORDER BY Num DESC

But with a large data set and other things attaching to it it got very slow Was hoping that I could get something better

Thank you

J


I am going to assume some ordering column called ord and a date column called dt:

Naively:

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

With your updated data, see how this performs:

https://data.stackexchange.com/stackoverflow/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;


I'm not sure what your implied sort order is. Is it the order the items are entered? If so, try adding an identity field. It will be incremented for each row you add. To figure out the row number for a particular row, just do a count of the records whose identity field are less than or equal to the target row.

If there's some other sort order you're intending, it's not clear from your example.


Need to have an Order by and your natural sort my be ParentID, MilestoneID and the syntax is trickier than you may have guessed. Without a an Order By clause there is no guaranteed sort (even if the table has a clustered PK). Cade I like you answer and I up ticked it but I could not post a code sample in a comment.

    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

I know there is a temptation to simplify this but I do lots of multi column sorts where I need to grab the next X rows and there are subtle ways to get burnt. For your simple count yes you may be able to simplify but I also think this will give you the correct answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜