簡體   English   中英

如何在SQL中使用子查詢使用“具有”和“分組依據”

[英]How to use “Having” and “Group By” using subqueries in SQL

請幫助在我的查詢中找到計數。 使用“具有”和“分組依據”時出現錯誤。

我已如下修改我的代碼以查找類似的事件計數。 我正在尋找基於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');

您不能在子查詢中選擇多個語句。 通常,我們還必須在子查詢內部與其父查詢建立關系。

我假設您想拉出子查詢中針對用戶的事件數,如果要這樣做,則必須如下代碼。

    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

您正在尋找一個相關的子查詢,而不是一個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()刪除,以簡化邏輯。

嘗試這個:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM