【问题标题】:MS SQL Join/Count QueryMS SQL 连接/计数查询
【发布时间】:2023-04-09 13:13:01
【问题描述】:

我有以下表格:

会话

  • ID(整数)
  • 用户 ID(整数)
  • 开始(日期时间)
  • 停止(日期时间)

用户

  • ID(整数)
  • 用户名 (nvarchar(200))

日志

  • SessionId (int)
  • Lo​​gLevelId (int)
  • 时间戳(日期时间)
  • 消息(varchar(max))

日志级别

  • ID(整数)
  • DisplayText (varchar(5))

我想要的是一个显示会话列表概览的输出,其中包含以下列:

SessionId | Username | Start | Stop | [total number of logs from each log level]

我在 C# 中有一个解决方案:

  1. 选择所有日志级别及其相关的显示文本
  2. 使用以下查询获取所有会话的列表:

-

SELECT [Sessions].[Id]
      ,[Username]
      ,[Start]
      ,[Stop]
      ,[Application]
  FROM [Sessions]
  JOIN [Users] ON [Users].[Id] = [UserId]
  1. 我循环遍历步骤 1 中的每个结果以组合查询以计算每个可能的日志级别。然后根据步骤 2 的结果执行查询,将 where 子句放在末尾以根据特定会话进行过滤。这些查询中的每一个都类似于以下内容:

-

SELECT 
     COUNT(CASE [Logs].[LogLevelId] WHEN 1 THEN 1 END) AS 'Debugs'
    ,COUNT(CASE [Logs].[LogLevelId] WHEN 2 THEN 1 END) as 'Infos'
    ,COUNT(CASE [Logs].[LogLevelId] WHEN 3 THEN 1 END) as 'Warnings'
    ,COUNT(CASE [Logs].[LogLevelId] WHEN 4 THEN 1 END) as 'Errors'
    ,COUNT(CASE [Logs].[LogLevelId] WHEN 5 THEN 1 END) as 'Fatals'
  FROM [Logs]
  WHERE [SessionId] = |C# SESSION ID HERE|

我知道这不是最佳解决方案,我想知道如何在单个查询或两个查询中而不是 2 个查询 + N 中提取所有这些信息,其中 N 是会话总数行。

【问题讨论】:

    标签: sql


    【解决方案1】:

    考虑在聚合GROUP BY 查询中加入前一个查询和后一个查询。

    SELECT l.SessionId
           , u.Username
           , s.Start
           , s.Stop
           , COUNT(CASE WHEN l.[LogLevelId] = 1 
                        AND lvl.DisplayText = 'Debugs' THEN 1 END) AS 'Debugs'
           , COUNT(CASE WHEN l.[LogLevelId] = 2 
                        AND lvl.DisplayText = 'Infos' THEN 1 END) as 'Infos'
           , COUNT(CASE WHEN l.[LogLevelId] = 3 
                        AND lvl.DisplayText = 'Warnings' THEN 1 END) as 'Warnings'
           , COUNT(CASE WHEN l.[LogLevelId] = 4 
                        AND lvl.DisplayText = 'Errors' THEN 1 END) as 'Errors'
           , COUNT(CASE WHEN l.[LogLevelId] = 5 
                        AND lvl.DisplayText = 'Fatals' THEN 1 END) as 'Fatals'
    FROM     
       [Sessions] s
       JOIN [Users] u ON u.[Id] = s.[UserId]
       JOIN [Logs] l ON l.[SessionId] = s.[Id]
       JOIN [LogLevels] lvl ON lvl.[Id] = l.[LogLevelId]
    
    GROUP BY l.[SessionId]
             , u.Username
             , s.Start
             , s.Stop
    

    【讨论】:

    • 这太完美了!我不知道你能做到这一点。有没有办法我也可以合并 Log 表的 Ids 和 DisplayNames。每个“COUNT(CASE t.[LogLevelId] WHEN 1 THEN 1 END) AS 'Debugs'”行实际上是一个 LogLevel 的 Id 和 DisplayName。
    • 子查询不是必须的。
    • 查看更新,根据需要调整CASE 逻辑。正如@GordonLinoff 指出的那样,不需要派生表,只需在聚合查询中连接所有表即可。
    猜你喜欢
    • 2014-03-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    相关资源
    最近更新 更多