计算每行结果的标准出现次数

时间:2016-07-14 02:42:40

标签: sql-server sql-server-2008

我试图在每行的基础上确定在特定时刻存在多少这些请求。

日期和时间专门用于在结果中以这种方式显示,但它们分别以默认yyyy-mm-dd00:00:00.000格式存储在数据库中

Request Data:

ID      |   CDate       |   CTime   |   LDate       |   LTime
---------------------------------------------------------------
230700  |   13/07/2016  |   6:52am  |   13/07/2016  |   7:21am 
746970  |   13/07/2016  |   7:05am  |   13/07/2016  |   7:10am 
746971  |   13/07/2016  |   7:09am  |   13/07/2016  |   7:09am 
746972  |   13/07/2016  |   7:16am  |   13/07/2016  |   7:27am
746973  |   13/07/2016  |   7:20am  |   13/07/2016  |   7:29am

CTime指的是问题创建时间,LTime指的是用户登录问题的时间。

我希望根据整个查询的结果在这些结果的末尾添加一个新列。新列将计算在任何给定时间可见的问题数量。问题在创建后立即可见,并在用户登录请求时消失,创建LTime条目。

在此示例中,我们将使用ID: 746970的第二行数据。我们可以看到创建时间为7:05am,但问题直到7:10am才会登录。在该登录时间,已经创建了2个其他问题,但尚未登录(230700746971),创建时间为6:52am / {{1} }和7:21am / 7:09am分别。因此,新列将报告登录时可见问题数量的7:09am值。

到目前为止,我的思维过程让我相信这需要2-3部分查询,可能会将结果存储在临时表中。查询的第一部分将获得上面显示的结果(已创建)。查询的第二部分将在“每行”的基础上确定有多少行3小于每行的CTime。然后,第三个查询将对第二个查询的结果运行另一个检查,以计算当前行的LTime等于或小于其他行的LTime的行数。

运行此操作后的结果如下所示。 方括号内的文字不会显示在结果中,只是包含在显示效果中。

LTime

New data:

我对这一点感到茫然,我知道它的逻辑,但不能为我的生活把它放到MS SQL代码中。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我要说的第一件事是你应该考虑改变你的表格,使得DATE和TIME字段不是分开的。除非您运行一大堆关心时间或关心日期的查询,并且您已经围绕此建立了索引,否则最好使用单个DATETIME列 - 它使运行的查询更加容易,同时需要日期和时间。

继续我认为是你的问题的解决方案(假设“活动”的标准是正确的)......简短的回答是你不需要任何临时表或任何东西(我的解决方案使用CTE但它甚至不需要那样):

DECLARE @ TABLE (ID INT PRIMARY KEY, CDate DATE NOT NULL, CTime TIME NOT NULL, LDate DATE NOT NULL, LTime TIME NOT NULL)
INSERT @ VALUES (230700, '2016-07-13', '06:52:00.000', '2016-07-13', '07:21:00.000')
, (746970, '2016-07-13', '07:05:00.000', '2016-07-13', '07:10:00.000')
, (746971, '2016-07-13', '07:09:00.000', '2016-07-13', '07:09:00.000')
, (746972, '2016-07-13', '07:16:00.000', '2016-07-13', '07:27:00.000')
, (746973, '2016-07-13', '07:20:00.000', '2016-07-13', '07:29:00.000');

WITH CTE AS (
    SELECT ID
         , CDate + CAST(CTime AS DATETIME) CDateTime
         , LDate + CAST(LTime AS DATETIME) LDateTime
    FROM @)
SELECT T.ID, T.CDateTime, T.LDateTime, Z.ActiveCount
FROM CTE T
OUTER APPLY (
    SELECT CAST(COUNT(*) AS VARCHAR(255)) 
           + ' (' +
           STUFF((SELECT ', ' + CAST(ID AS VARCHAR(255))
            FROM CTE
            WHERE CDateTime <= T.LDateTime
            AND LDateTime >= T.LDateTime
            ORDER BY ID
            FOR XML PATH ('')), 1, 2, '') + ')'
           -- COUNT(*) -- this just produces the number
    FROM CTE
    WHERE CDateTime <= T.LDateTime
    AND LDateTime >= T.LDateTime) Z(ActiveCount)

如果您需要将日期和时间字段分开,则可以将该语句重写为:

DECLARE @ TABLE (ID INT PRIMARY KEY, CDate DATE NOT NULL, CTime TIME NOT NULL, LDate DATE NOT NULL, LTime TIME NOT NULL)
INSERT @ VALUES (230700, '2016-07-13', '06:52:00.000', '2016-07-13', '07:21:00.000')
, (746970, '2016-07-13', '07:05:00.000', '2016-07-13', '07:10:00.000')
, (746971, '2016-07-13', '07:09:00.000', '2016-07-13', '07:09:00.000')
, (746972, '2016-07-13', '07:16:00.000', '2016-07-13', '07:27:00.000')
, (746973, '2016-07-13', '07:20:00.000', '2016-07-13', '07:29:00.000');

SELECT T.ID
     , CONVERT(VARCHAR(255), T.CDate, 103) CDate
     , CONVERT(VARCHAR(255), T.CTime, 100) CTime
     , CONVERT(VARCHAR(255), T.LDate, 103) LDate
     , CONVERT(VARCHAR(255), T.LTime, 100) LTime
     , Z.ActiveCount
FROM @ T
OUTER APPLY (
    SELECT COUNT(*) -- this just produces the number
    FROM @
    WHERE CDate + CAST(CTime AS DATETIME) <= T.LDate + CAST(T.LTime AS DATETIME)
    AND LDate + CAST(LTime AS DATETIME) >= T.LDate + CAST(T.LTime AS DATETIME)) Z(ActiveCount)