簡體   English   中英

如何連接三個表並使用UNION一列計算記錄

[英]How to join three tables and count the record with UNION one column

我想加入這些表並計算狀態是否為'Y'

table1(date, status)
8/23/2015    Y
8/24/2015    Y
8/24/2015    N

table2(date, status)
8/23/2015    Y
8/23/2015    Y

table3(date, status)
8/23/2015    Y
8/25/2015    N
8/25/2015    Y

我期望的結果就像。

DATE       count(table1.status)  count(table2.status)  count(table3.status)
---------  --------------------  --------------------  --------------------
8/23/2015  1                     2                     1
8/24/2015  1                     0                     0
8/25/2015  0                     0                     1

也許最簡單的方法是將union all表合並在一起然后聚合:

select date, sum(status1) as status1, sum(status2) as status2,
       sum(status3) as status3
from ((select date, 1 as status1, 0 as status2 , 0 as status3
       from table1
       where status = 'Y') union all
      (select date, 0 as status1, 1 as status2 , 0 as status3
       from table2
       where status = 'Y') union all
      (select date, 0 as status1, 0 as status2 , 1 as status3
       from table3
       where status = 'Y') 
     ) t
group by date
order by date;

如果你想通過full join來做這件事,你必須非常小心。 你很想寫:

select date,
       sum(case when t1.status1 = 'Y' then 1 else 0 end) as status1, 
       sum(case when t2.status1 = 'Y' then 1 else 0 end) as status2, 
       sum(case when t3.status1 = 'Y' then 1 else 0 end) as status3 
from table1 t1 full join
     table2 t2
     using (date) full join
     table3 t3
     using (date)
group by date
order by date;

但是,當同一日期在不同的表中有多個計數(日期的笛卡爾積)時,這會出現問題。 所以,下一個誘惑是增加count(distinct) 在這種情況下你可以這樣做,因為沒有唯一的列。 即使有,這也增加了開銷。

最后,如果您想沿着這條路走下去,可以通過預先聚合每個表來解決這個問題。

這是另一種選擇:

with table1 as (select to_date('23/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('24/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('25/08/2015', 'dd/mm/yyyy') dt, 'N' status from dual),
     table2 as (select to_date('23/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('23/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('26/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual),
     table3 as (select to_date('23/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('25/08/2015', 'dd/mm/yyyy') dt, 'Y' status from dual union all
                select to_date('25/08/2015', 'dd/mm/yyyy') dt, 'N' status from dual)
select coalesce(t1.dt, t2.dt, t3.dt) dt,
       coalesce(t1.cnt, 0) t1_cnt,
       coalesce(t2.cnt, 0) t2_cnt,
       coalesce(t3.cnt, 0) t3_cnt
from   (select dt, count(case when status = 'Y' then 1 end) cnt
        from table1
        group by dt) t1
       full outer join (select dt, count(case when status = 'Y' then 1 end) cnt
                        from table2
                        group by dt) t2 on t1.dt = t2.dt
       full outer join (select dt, count(case when status = 'Y' then 1 end) cnt
                        from table3
                        group by dt) t3 on t1.dt = t3.dt
order by coalesce(t1.dt, t2.dt, t3.dt);


DT             T1_CNT     T2_CNT     T3_CNT
---------- ---------- ---------- ----------
23/08/2015          1          2          1
24/08/2015          1          0          0
25/08/2015          0          0          1
26/08/2015          0          1          0

(它連接到其他表之前將每行的行聚合到一行,因此您不會在計數中包含重復的行)。

這是一個好玩的問題。

為了得到結果,我們可以通過使用解碼函數對其進行“Y”值求和,如下所示。

create table table1(date1 date, status varchar2(2)) 
insert into table1 values ( to_date( '8/23/2015', 'mm/dd/yyyy'), 'Y');
insert into table1 values ( to_date( '8/24/2015', 'mm/dd/yyyy'), 'Y');
insert into table1 values ( to_date( '8/24/2015', 'mm/dd/yyyy'), 'N');

create table table2(date1 date, status varchar2(2))
insert into table2 values ( to_date( '8/23/2015', 'mm/dd/yyyy'), 'Y');
insert into table2 values ( to_date( '8/23/2015', 'mm/dd/yyyy'), 'Y');

create table table3(date1 date, status varchar2(2))
insert into table3 values ( to_date( '8/23/2015', 'mm/dd/yyyy'), 'Y');
insert into table3 values ( to_date( '8/25/2015', 'mm/dd/yyyy'), 'N');
insert into table3 values ( to_date( '8/25/2015', 'mm/dd/yyyy'), 'Y');

select date1,
       sum(decode(x, '1', status, null)), -- table1:x=1
       sum(decode(x, '2', status, null)), -- table2:x=2
       sum(decode(x, '3', status, null))  -- table3:x=3
  from (select 1 x, date1, decode(status, 'Y', 1, 0) status
          from table1
        union all
        select 2 x, date1, decode(status, 'Y', 1, 0) status
          from table2
        union all
        select 3 x, date1, decode(status, 'Y', 1, 0) status
          from table3)
 group by date1
 order by 1

在@Gordon Linoff解決方案中,他創建了3列(status1,status2,status3)來獲得結果,在此解決方案中,我直接從數據中獲得結果。

通往羅馬的所有道路。

檢查一下

select  t1.DATE,
SUM(NVL(decode(t1.status, 'Y', 1, 0)),0) table1_sum,
SUM(NVL(decode(t2.status, 'Y', 1, 0)),0) table2_sum,
SUM(NVL(decode(t3.status, 'Y', 1, 0)),0) table3_sum
from table1 t1,
join table2 t2,
join table3 t3,
where t1.Date = t2.date and t1.Date = t3.date
group by t1.DATE
order by t1.DATE

暫無
暫無

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

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