SQL查询按组返回前X个连续降序行的特定值

时间:2009-12-11 21:53:34

标签: sql tsql

我需要一个查询,按组返回true或false,如果按降序日期顺序排列的最新x个连续行的列具有false值,其中x对于每个组可能不同。

例如,配置表将具有必须按companyId和serviceId顺序匹配的记录数:

CompanyId     ServiceId      NumberOfMatchingSequentialRecords
2             1              3
3             2              2

要查询的表,例如Logging,可能包含以下数据:

CompanyId     ServiceId     SuccessfulConnect(bit)     CreateDate (desc order)
2             1             0                          2009-12-09  9:54am
2             1             0                          2009-12-09  9:45am
2             1             0                          2009-12-09  9:36am
2             1             1                          2009-12-08 10:16am
2             1             1                          2009-12-07  3:24pm

3             2             0                          2009-10-15 8:54am
3             2             1                          2009-10-14 5:17pm
3             2             0                          2009-10-13 4:32am
3             2             1                          2009-10-13 1:19am

要匹配的查询,SuccessfulConnect必须具有按组划分的0 / false值(companyId,serviceId)。

查询的结果将是......

CompanyId     ServiceId     Alert (bit)
2             1             1
3             2             0

...因为companyId = 2,serviceId = 1会返回一个true,因为在Configuration表中定义的,按降序日期顺序排列的3个最近的连续记录都将SuccessfulConnect设为false。

但是,companyId = 3 serviceId = 2将返回false,因为在Configuration表中定义的按降序日期顺序排列的2个最近的连续记录都没有错误。

1 个答案:

答案 0 :(得分:2)

我认为您需要以下内容。

    SELECT 
        T.CompanyId, T.ServiceId, 
        CASE WHEN SUM(CAST(SuccessfulConnect AS int)) = 0 THEN 1 ELSE 0 END AS Alert
    FROM (
        SELECT
            CompanyId, ServiceId, SuccessfulConnect,
            ROW_NUMBER() OVER (PARTITION BY CompanyId, ServiceId 
                ORDER BY CreateDate DESC) AS intRow
        FROM Logging
    ) AS T
        INNER JOIN Configuration c ON c.CompanyId = T.CompanyId
            AND c.ServiceId = T.ServiceId
    WHERE intRow <= c.NumberOfMatchingSequentialRecords
    GROUP BY T.CompanyId, T.ServiceId, c.NumberOfMatchingSequentialRecords
    HAVING COUNT(*) >= C.NumberOfMatchingSequentialRecords

您可以使用以下方法进行测试:

CREATE TABLE Configuration (CompanyId int, ServiceId int, NumberOfMatchingSequentialRecords int)
CREATE TABLE Logging (CompanyId int, ServiceId int, SuccessfulConnect bit, CreateDate datetime)

INSERT Configuration VALUES (2, 1, 3)
INSERT Configuration VALUES (3, 2, 2)
INSERT Logging VALUES (2, 1, 0, '2009-12-09  9:54am')
INSERT Logging VALUES (2, 1, 0, '2009-12-09  9:45am')
INSERT Logging VALUES (2, 1, 0, '2009-12-09  9:36am')
INSERT Logging VALUES (2, 1, 1, '2009-12-08 10:16am')
INSERT Logging VALUES (2, 1, 1, '2009-12-07  3:24pm')
INSERT Logging VALUES (3, 2, 0, '2009-10-15 8:54am')
INSERT Logging VALUES (3, 2, 1, '2009-10-14 5:17pm')
INSERT Logging VALUES (3, 2, 0, '2009-10-13 4:32am')
INSERT Logging VALUES (3, 2, 1, '2009-10-13 1:19am')

SELECT 
    T.CompanyId, T.ServiceId, 
    CASE WHEN SUM(CAST(SuccessfulConnect AS int)) = 0 THEN 1 ELSE 0 END AS Alert
FROM (
    SELECT
        CompanyId, ServiceId, SuccessfulConnect,
        ROW_NUMBER() OVER (PARTITION BY CompanyId, ServiceId 
            ORDER BY CreateDate DESC) AS intRow
    FROM Logging
) AS T
    INNER JOIN Configuration c ON c.CompanyId = T.CompanyId
        AND c.ServiceId = T.ServiceId
WHERE intRow <= c.NumberOfMatchingSequentialRecords
GROUP BY T.CompanyId, T.ServiceId, c.NumberOfMatchingSequentialRecords
HAVING COUNT(*) >= C.NumberOfMatchingSequentialRecords

DROP TABLE Logging
DROP TABLE Configuration

这给出了:

CompanyId    ServiceId    Alert
    2            1          1
    3            2          0