【问题标题】:How to use "Having" and "Group By" using subqueries in SQL如何在 SQL 中使用子查询来使用“Having”和“Group By”
【发布时间】:2023-03-26 12:00:01
【问题描述】:

请帮助在我的查询中查找计数。使用“have”和“group by”时出现错误。

我已经修改了我的代码,如下所示,以查找类似的事件计数。我正在寻找基于 2 个字段(user_id,item_id)的计数

SELECT 
    i.usr_id,
    COUNT(DISTINCT CASE WHEN inc_data.Rep3 = 'y' THEN 1 END) AS RespBreach,
    COUNT(DISTINCT CASE WHEN inc_data.Res3 = 'y' THEN 1 END) AS ResBreach,
    COUNT(DISTINCT i.incident_id) as CallCount,
    SUM(CASE WHEN act1.act_type= 'TRAVEL' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Travel_Time,
    SUM(CASE WHEN act1.act_type= 'REMOTE' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Remote_Time,
    (SELECT 
         COUNT(inc.incident_id) AS similar_inc_count, 
         inc.item_id, inc.cust_id 
     FROM
         incident inc
     GROUP BY 
         inc.usr_id, inc.item_id
     HAVING      
         (COUNT(inc.incident_id) > 1)) AS similar_Call    
FROM 
    incidents AS i
INNER JOIN 
    inc_data ON i.incident_id = inc_data.incident_id
INNER JOIN 
    actions act1 ON i.incident_id = act1.incident_id 
WHERE 
    i.date_logged BETWEEN '2016-08-20' AND '2016-08-23' 
GROUP BY 
    i.usr_id

预期结果:

| user_id | RespBreach | ResBreach | CallCount | Travel_Time | Remote_Time | Similer_call |
+---------+------------+-----------+-----------+-------------+-------------+--------------+
|     111 |          1 |         1 |         2 |         140 |          50 |            0 |
|     190 |          1 |         0 |         2 |          75 |          60 |            1 |
+---------+------------+-----------+-----------+-------------+-------------+--------------+

样本数据:

CREATE TABLE incidents (incident_id int,date_logged datetime,usr_id int,dept_id int,item_id int, cust_id int)  

insert into incidents values 
('1001',    '8/20/2016',    '190',  '3',    '800',  '10'),
('1002',    '8/21/2016',    '111',  '4',    '810',  '12'),
('1003',    '8/22/2016',    '190',  '3',    '800',  '10'),
('1004',    '8/23/2016',    '111',  '4',    '822',  '12')


Create TABLE actions ( act_id int, act_type varchar(50) ,   incident_id int,    usr_id   int ,date_actioned datetime,   service_time money)

Insert into actions VALUES
('1',   'TRAVEL',   1001,   190,    8/20/2016,  20),
('2',   'ASSIGN',   1001,   2,  8/21/2016,  1),
('3',   'TRAVEL',   1001,   190 ,8/22/2016, 10),
('4',   'REMOTE',   1001,   190,    8/23/2016,  30),
('5',   'TRAVEL',   1002,   111,    8/21/2016,  40),
('6',   'ASSIGN',   1002,   2,  8/22/2016   ,1),
('7',   'REMOTE',   1002,   111,    8/23/2016,  30),
('8',   'TRAVEL',   1002,   111,    8/24/2016,  60),
('9',   'TRAVEL',   1003,   190,    8/22/2016,  45),
('10',  'ASSIGN',   1003,   2,  8/23/2016   ,1),
('11',  'REMOTE',   1003,   190 ,8/23/2016  ,10),
('12',  'REMOTE',   1003,   190 ,8/23/2016  ,20),
('13',  'ASSIGN',   1004,   2   ,8/23/2016  ,1),
('14',  'TRAVEL',   1004,   111,    8/23/2016,  20),
('15',  'TRAVEL',   1004,   111,    8/23/2016,  20),
('16',  'REMOTE',   1004,   111,    8/23/2016,  20)


CREATE TABLE inc_data (incident_id int,Rep1 char(1), Rep2 char(1),  Rep3 char(1),   Res1 char(1),   Res2 char(1),   Res3 char(1))   

insert into inc_data values
(1001,  'y',    'y',    'y',    'y',    'y',    'n'),
(1002,  'n',    'n',    'n',    'n',    'n',    'n'),
(1003,  'y',    'y',    'n',    'n',    'n',    'n'),
(1004,  'y',    'y',    'y',    'y' ,   'y',    'y');

【问题讨论】:

  • 您的查询有一些语法问题。也许你可以让我们知道查询应该做什么?
  • @TimBiegeleisen 你可以在这里找到我的桌子“rextester.com/OQPY39298
  • 我希望根据 2 个字段 (user_id,item_id) 找到计数
  • 您应该在问题中包含此信息。 Stack Overflow 不是泵和转储服务。
  • @TimBiegeleisen 抱歉提供的信息很少。以备将来使用。

标签: sql sql-server database sql-server-2008


【解决方案1】:

您不能在子查询中选择多个语句。通常我们还必须在子查询中与其父查询建立关系。

我假设您想在子查询中提取针对用户的事件数量,如果是这样,您必须编写如下代码..

    SELECT i.usr_id,
       COUNT(DISTINCT CASE WHEN inc_data.Rep3 = 'y' THEN 1 END) AS RespBreach,
       COUNT(DISTINCT CASE WHEN inc_data.Res3 = 'y' THEN 1 END) AS ResBreach,
       COUNT(DISTINCT i.incident_id) as CallCount,
       SUM(CASE WHEN act1.act_type= 'TRAVEL' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Travel_Time,
       SUM(CASE WHEN act1.act_type= 'REMOTE' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Remote_Time,
      ISNULL((SELECT     COUNT(inc.incident_id) -1
         FROM incidents inc
         WHERE inc.usr_id=i.usr_id 
           GROUP BY inc.usr_id,inc.item_id
             HAVING COUNT(inc.incident_id) > 1 
             ),0)AS similar_inc_count   
FROM incidents as i
INNER JOIN inc_data ON i.incident_id= inc_data.incident_id
INNER JOIN actions act1 on i.incident_id=act1.incident_id 
WHERE i.date_logged BETWEEN '2016-08-20' AND '2016-08-23' 
GROUP BY i.usr_id

【讨论】:

  • 感谢您的建议和咨询。我可以跳过这个块吗?” COUNT(similer_inc_count)as similer_inc_count ,“
  • 如果我想使用 ISNULL 如何将它用于 simile_call 结果
  • ISNULL((SELECT COUNT(inc.incident_id) from events inc GROUP BY inc.usr_id, inc.item_id HAVING COUNT(inc.incident_id) > 1),0) AS similar_Call
  • 只需使用 isnull 函数为该选定字段放置一个外部覆盖物..我仍然不知道您在子查询中实际需要什么..根据您的需要修改查询..当前如果事件计数大于 2,查询将拉取针对用户的所有事件。
  • @Salman 您的代码中没有类似 similer_inc_count 的列。
【解决方案2】:

您正在寻找相关子查询,而不是group by。但是,您的查询还有其他改进:

SELECT i.usr_id,
       MAX(CASE WHEN id.Rep3 = 'y' THEN 1 ELSE 0 END) AS RespBreach,
       MAX(CASE WHEN id.Res3 = 'y' THEN 1 ELSE 0 END) AS ResBreach,
       COUNT(DISTINCT i.incident_id) as CallCount,
       SUM(CASE WHEN a.act_type = 'TRAVEL'
                THEN a.service_time
                ELSE 0
           END) AS Travel_Time,
       SUM(CASE WHEN a.act_type = 'REMOTE'
                THEN a.service_time
                ELSE 0
           END) AS Remote_Time,    
        (SELECT COUNT(*) AS similar_inc_count
         FROM (SELECT inc.item_id
               FROM incident inc
               WHERE inc.cust_id = i.user_id
               GROUP BY inc.item_id
               HAVING COUNT(inc.incident_id) > 1)
              ) inc
        ) AS similar_Call    
FROM incidents i INNER JOIN
     inc_data id
     ON i.incident_id = id.incident_id INNER JOIN
     actions a 
     ON i.incident_id = a.incident_id 
WHERE i.date_logged BETWEEN '2016-08-20' AND '2016-08-23' 
GROUP BY i.usr_id;

注意事项:

  • 子查询是我对您意图的最佳猜测。它会为用户计算发生多个事件的项目数。
  • COUNT(DISTINCT) 已替换为 MAX()MAX() 更易于理解且更高效。
  • IFNULL() 已从 SUM() 中删除以简化逻辑。

【讨论】:

  • 它给了我语法错误:“Msg 102, Level 15, State 1, Line 20 Incorrect syntax near ')'。”
【解决方案3】:

试试这个:

SELECT i.usr_id,
       COUNT(DISTINCT CASE WHEN inc_data.Rep3 = 'y' THEN 1 END) AS RespBreach,
       COUNT(DISTINCT CASE WHEN inc_data.Res3 = 'y' THEN 1 END) AS ResBreach,
       COUNT(DISTINCT i.incident_id) as CallCount,
       SUM(CASE WHEN act1.act_type= 'TRAVEL' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Travel_Time,
       SUM(CASE WHEN act1.act_type= 'REMOTE' THEN ISNULL(act1.service_time, 0) ELSE 0 END) AS Remote_Time,
        (SELECT COUNT(inc.incident_id)
         FROM incidents inc
         GROUP BY inc.usr_id, inc.item_id
         HAVING COUNT(inc.incident_id) > 1) AS similar_Call    
FROM incidents as i
INNER JOIN inc_data ON i.incident_id= inc_data.incident_id
INNER JOIN actions act1 on i.incident_id=act1.incident_id 
WHERE i.date_logged BETWEEN '2016-08-20' AND '2016-08-23' 
GROUP BY i.usr_id

【讨论】:

  • 感谢您的询问,我们需要使用 Unnikrishnan 建议的 Where 子句。
猜你喜欢
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-04-25
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
相关资源
最近更新 更多