将数据可能不匹配的两组数据连接起来

时间:2018-10-01 08:55:42

标签: sql sql-server tsql

我有两组数据要合并并同时返回,但是我需要连接的列可能在集合A中有一个值,而在集合B中没有,反之亦然,所以LEFT / RIGHT JOIN并不理想。

设置A

查询-

SELECT o.organisation_id, 
       Count(call_opened)           'opened calls',
       Format(call_opened, 'MMM-yy')'month name', 
       call_severity 
FROM   call c 
       JOIN users u 
         ON u.user_id = c.user_id 
       JOIN organisation o 
         ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
          Format(call_opened, 'MMM-yy'), 
          call_severity

返回-

organisation_id opened calls    month name  call_severity
BES             1               Apr-12      3
BES             1               Dec-13      3
BES             1               Jun-12      3
BES             1               Mar-12      3
BES             2               Nov-11      3
BES             1               Oct-11      3

设置B

查询-

SELECT o.organisation_id, 
       Count(call_closed)           'closed calls', 
       Format(call_closed, 'MMM-yy')'month name', 
       call_severity 
FROM   call c 
       JOIN users u 
         ON u.user_id = c.user_id 
       JOIN organisation o 
         ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
          Format(call_closed, 'MMM-yy'), 
          call_severity

返回-

organisation_id closed calls    month name  call_severity
BES             2               Aug-13      3
BES             1               Dec-11      3
BES             1               Dec-13      3
BES             1               Mar-12      3
BES             1               Nov-11      3
BES             1               Sep-12      3

到目前为止

查询-

SELECT opened.organisation_id, 
       Isnull(opened.[opened calls],0) 'opened calls',  
       Isnull(closed.[closed calls],0) 'closed calls',  
       opened.[month name], 
       opened.call_severity 
FROM   (SELECT o.organisation_id, 
               Count(call_opened)           'opened calls', 
               Format(call_opened, 'MMM-yy')'month name', 
               call_severity 
        FROM   call c 
               JOIN users u 
                 ON u.user_id = c.user_id 
               JOIN organisation o 
                 ON o.organisation_id = u.organisation_id
        WHERE  Call_Type = 'FT'
        GROUP  BY o.organisation_id, 
                  Format(call_opened, 'MMM-yy'), 
                  call_severity) opened 
       LEFT JOIN (SELECT o.organisation_id, 
                         Count(call_closed)           'closed calls', 
                         Format(call_closed, 'MMM-yy')'month name', 
                         call_severity 
                  FROM   call c 
                         JOIN users u 
                           ON u.user_id = c.user_id 
                         JOIN organisation o 
                           ON o.organisation_id = u.organisation_id
                  WHERE  Call_Type = 'FT'
                  GROUP  BY o.organisation_id, 
                            Format(call_closed, 'MMM-yy'), 
                            call_severity) closed 
         ON opened.organisation_id = closed.organisation_id 
            AND opened.[month name] = closed.[month name] 
            AND opened.call_severity = closed.call_severity
WHERE opened.Call_Severity <> 5
ORDER  BY opened.organisation_id ASC

返回-

organisation_id opened calls    closed calls    month name  call_severity
BES             1               0               Apr-12      3
BES             1               1               Dec-13      3
BES             1               0               Jun-12      3
BES             1               1               Mar-12      3
BES             2               1               Nov-11      3
BES             1               0               Oct-11      3

如您所见,由于集合B包含集合A中不存在的月份数据,因此这不会返回我需要的数据。

理想情况下,我希望这样返回数据-

organisation_id opened calls    closed calls    month name  call_severity
BES             1               0               Apr-12      3
BES             1               1               Dec-13      3
BES             1               0               Jun-12      3
BES             1               1               Mar-12      3
BES             2               1               Nov-11      3
BES             1               0               Oct-11      3
BES             0               2               Aug-13      3
BES             0               1               Dec-11      3
BES             0               1               Sep-12      3

我考虑过要创建一个初始临时表,然后插入月份值并加入结果集,但是由于数据要回溯到2002年,所以这太麻烦了,太杂乱了,这是我可能或会做的我需要重做我的解决方案吗?

我认为这是调用表中需要的所有数据-

Call_ID     Call_Opened                Call_Closed              Call_Severity   User_id
28000001    2011-10-19 13:13:48.000    2011-11-09 11:47:03.000  3               825
28000002    2011-11-07 10:55:24.000    2012-03-05 08:27:54.000  3               825
28000003    2011-11-21 09:11:49.000    2011-12-19 08:41:36.000  3               825
28000006    2012-03-30 15:11:23.000    2013-08-29 15:51:39.000  3               825
28000007    2012-04-02 11:50:22.000    2013-08-29 15:52:11.000  3               825
28000008    2012-06-25 08:12:39.000    2012-09-28 16:32:08.000  3               825
28000012    2013-12-17 07:41:26.000    2013-12-17 08:58:35.000  3               825

4 个答案:

答案 0 :(得分:2)

这是使用cross apply的好地方:

SELECT o.organisation_id, 
       SUM(v.is_open) as opened_calls,
       SUM(v.is_close) as closed_calls,
       Format(call_time, 'MMM-yy') as month_name, 
       call_severity 
FROM call c JOIN
     users u 
     ON u.user_id = c.user_id JOIN
     organisation o 
     ON o.organisation_id = u.organisation_id CROSS APPLY
     (VALUES (call_opened, 1, 0 ), 
             (call_closed, 0, 1)
     ) as v(call_time, is_open, is_close)
WHERE Call_Type = 'FT'
GROUP BY o.organisation_id, 
         Format(call_time, 'MMM-yy'), 
         call_severity

答案 1 :(得分:1)

您应使用UNION ALL进行公开通话/结束呼叫,然后在顶部查询中使用group。请参阅下面的样机。 让我知道您是否有任何问题。

SELECT organisation_id, 
       Isnull(SUM([opened calls]),0) 'opened calls',  
       Isnull(SUM([closed calls]),0) 'closed calls',  
       [month name], 
       call_severity 
FROM   (
---Set A 
SELECT o.organisation_id, 
       Count(call_opened)           'opened calls',
       0 'closed calls',
       Format(call_opened, 'MMM-yy')'month name', 
       call_severity 
FROM   call c 
       JOIN users u 
         ON u.user_id = c.user_id 
       JOIN organisation o 
         ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
          Format(call_opened, 'MMM-yy'), 
          call_severity


UNION ALL   ---Set B

SELECT o.organisation_id, 
       0  'opened calls',
       Count(call_closed)           'closed calls', 
       Format(call_closed, 'MMM-yy')'month name', 
       call_severity 
FROM   call c 
       JOIN users u 
         ON u.user_id = c.user_id 
       JOIN organisation o 
         ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
          Format(call_closed, 'MMM-yy'), 
          call_severity
)S

GROUP BY
    organisation_id,
    [month name],
    call_severity

答案 2 :(得分:0)

您必须使用工会

select organisation_id
, sum(opened_calls) opened_calls
, sum(closed_calls) closed_calls
, month_name 
, call_severity
from (
SELECT o.organisation_id, 
   Count(call_opened)           opened_calls,
   0                            closed_calls,
   Format(call_opened, 'MMM-yy') month_name, 
   call_severity 
FROM   call c 
   JOIN users u 
     ON u.user_id = c.user_id 
   JOIN organisation o 
     ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
      Format(call_opened, 'MMM-yy'), 
      call_severity
union 
SELECT o.organisation_id, 
   0                            opened_calls
   Count(call_closed)           closed_calls, 
   Format(call_closed, 'MMM-yy') month_name, 
   call_severity 
FROM   call c 
   JOIN users u 
     ON u.user_id = c.user_id 
   JOIN organisation o 
     ON o.organisation_id = u.organisation_id
WHERE  Call_Type = 'FT'
GROUP  BY o.organisation_id, 
      Format(call_closed, 'MMM-yy'), 
      call_severity
)tt
group by organisation_id, month_name, call_severity 

答案 3 :(得分:0)

;WITH opened AS
(
    SELECT o.organisation_id, 
           Count(call_opened)           AS call_opened,
           Format(call_opened, 'MMM-yy') AS month_name, 
           call_severity 
    FROM   call c 
           JOIN users u 
             ON u.user_id = c.user_id 
           JOIN organisation o 
             ON o.organisation_id = u.organisation_id
    WHERE  Call_Type = 'FT'
    GROUP  BY o.organisation_id, 
              Format(call_opened, 'MMM-yy'), 
              call_severity
),
closed AS
 (
    SELECT o.organisation_id, 
           Count(call_closed)           AS call_closed, 
           Format(call_closed, 'MMM-yy') AS month_name, 
           call_severity 
    FROM   call c 
           JOIN users u 
             ON u.user_id = c.user_id 
           JOIN organisation o 
             ON o.organisation_id = u.organisation_id
    WHERE  Call_Type = 'FT'
    GROUP  BY o.organisation_id, 
              Format(call_closed, 'MMM-yy'), 
              call_severity
)
 SELECT COALESCE(opened.organisation_id, closed.organisation_id) AS organisation_id, 
 COALESCE(opened.call_opened, 0) AS call_opened, COALESCE(closed.call_closed, 0) AS call_closed, 
 COALESCE(opened.month_name, closed.month_name) AS month_name, 
 COALESCE(opened.call_severity, closed.call_severity) AS call_severity
 FROM opened 
 FULL OUTER JOIN closed 
 ON opened.month_name = closed.month_name;