2017-06-15 95 views
1

以下this post,我將@Vao Tsun給出的答案應用於這次由4個表格組成的較大數據集,而不是上面提到的相關帖子中的2個表格時,仍然存在問題。FULL OUTER JOIN將表與PostgreSQL合併

這裏是我的數據集:

-- Table 'brcht' (empty) 

insee | annee | nb 
-------+--------+----- 


-- Table 'cana' 

insee | annee | nb 
-------+--------+----- 
036223 | 2017 | 1 
086001 | 2016 | 2 


-- Table 'font' (empty) 

insee | annee | nb 
-------+--------+----- 


-- Table 'nr' 

insee | annee | nb 
-------+--------+----- 
036223 | 2013 | 1 
036223 | 2014 | 1 
086001 | 2013 | 1 
086001 | 2014 | 2 
086001 | 2015 | 4 
086001 | 2016 | 2 

下面是該查詢:

SELECT 
COALESCE(brcht.insee, cana.insee, font.insee, nr.insee) AS insee, 
COALESCE(brcht.annee, cana.annee, font.annee, nr.annee) AS annee, 
COALESCE(brcht.nb,0) AS brcht, 
COALESCE(cana.nb,0) AS cana, 
COALESCE(font.nb,0) AS font, 
COALESCE(nr.nb,0) AS nr, 
COALESCE(brcht.nb,0) + COALESCE(cana.nb,0) + COALESCE(font.nb,0) + COALESCE(nr.nb,0) AS total 

FROM public.brcht 
    FULL OUTER JOIN public.cana ON brcht.insee = cana.insee AND brcht.annee = cana.annee 
    FULL OUTER JOIN public.font ON cana.insee = font.insee AND cana.annee = font.annee 
    FULL OUTER JOIN public.nr ON font.insee = nr.insee AND font.annee = nr.annee 

ORDER BY COALESCE(brcht.insee, cana.insee, font.insee, nr.insee), COALESCE(brcht.annee, cana.annee, font.annee, nr.annee); 

在結果,我還是有兩行,而不是一個insee='086001'(見下文)。我需要獲得每個insee一行,在此示例中,兩個2值應與total列顯示4值在同一行上。

enter image description here

再次感謝您的幫助!


下面是SQL腳本來創建輕鬆上述表:

CREATE TABLE public.brcht (insee CHARACTER VARYING(10), annee INTEGER, nb INTEGER); 
CREATE TABLE public.cana (insee CHARACTER VARYING(10), annee INTEGER, nb INTEGER); 
CREATE TABLE public.font (insee CHARACTER VARYING(10), annee INTEGER, nb INTEGER); 
CREATE TABLE public.nr (insee CHARACTER VARYING(10), annee INTEGER, nb INTEGER); 

INSERT INTO public.cana (insee, annee, nb) VALUES ('036223', 2017, 1), ('086001', 2016, 2); 
INSERT INTO public.nr(insee, annee, nb) VALUES ('036223', 2013, 1), ('036223', 2014, 1), ('086001', 2013, 1), ('086001', 2014, 2), ('086001', 2015, 4), ('086001', 2016, 2); 

回答

1

由其他答案的啓發,但也許是更好的組織:

SELECT *, 
     brcht + cana + font + nr AS total 
FROM (SELECT insee, 
       annee, 
       SUM(Coalesce(brcht.nb, 0)) brcht, 
       SUM(Coalesce(cana.nb, 0)) cana, 
       SUM(Coalesce(font.nb, 0)) font, 
       SUM(Coalesce(nr.nb, 0)) nr 
     FROM brcht 
       full outer join cana USING (insee, annee) 
       full outer join font USING (insee, annee) 
       full outer join nr USING (insee, annee) 
     GROUP BY insee, 
        annee) t 
ORDER BY insee, 
      annee; 

,並提供:

insee | annee | brcht | cana | font | nr | total 
--------+-------+-------+------+------+----+------- 
036223 | 2013 |  0 | 0 | 0 | 1 |  1 
036223 | 2014 |  0 | 0 | 0 | 1 |  1 
036223 | 2017 |  0 | 1 | 0 | 0 |  1 
086001 | 2013 |  0 | 0 | 0 | 1 |  1 
086001 | 2014 |  0 | 0 | 0 | 2 |  2 
086001 | 2015 |  0 | 0 | 0 | 4 |  4 
086001 | 2016 |  0 | 2 | 0 | 2 |  4 
(7 rows) 
+0

非常明確,謝謝!不知道關於'USING'語句的連接。 – wiltomap

0

嘗試:

t=# SELECT 
COALESCE(brcht.insee, cana.insee, font.insee, nr.insee) AS insee, 
COALESCE(brcht.annee, cana.annee, font.annee, nr.annee) AS annee, 
COALESCE(brcht.nb,0) AS brcht, 
COALESCE(cana.nb,0) AS cana, 
COALESCE(font.nb,0) AS font, 
COALESCE(nr.nb,0) AS nr, 
COALESCE(brcht.nb,0) + COALESCE(cana.nb,0) + COALESCE(font.nb,0) + COALESCE(nr.nb,0) AS total 
FROM public.brcht 
    FULL OUTER JOIN public.cana ON brcht.insee = cana.insee AND brcht.annee = cana.annee 
    FULL OUTER JOIN public.font ON cana.insee = font.insee AND cana.annee = font.annee 
    FULL OUTER JOIN public.nr ON cana.insee = nr.insee AND cana.annee = nr.annee 
ORDER BY COALESCE(brcht.insee, cana.insee, font.insee, nr.insee), COALESCE(brcht.annee, cana.annee, font.annee, nr.annee); 
insee | annee | brcht | cana | font | nr | total 
--------+-------+-------+------+------+----+------- 
036223 | 2013 |  0 | 0 | 0 | 1 |  1 
036223 | 2014 |  0 | 0 | 0 | 1 |  1 
036223 | 2017 |  0 | 1 | 0 | 0 |  1 
086001 | 2013 |  0 | 0 | 0 | 1 |  1 
086001 | 2014 |  0 | 0 | 0 | 2 |  2 
086001 | 2015 |  0 | 0 | 0 | 4 |  4 
086001 | 2016 |  0 | 2 | 0 | 2 |  4 
(7 rows) 

在你的榜樣,你加入nrfont,而你可能想加入它對cana?..

也請求e檢查出在這裏: https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-JOIN

在沒有括弧,JOIN子句窩左到右

更新

解釋邏輯: 嘗試select * from public.brcht,加入其他表一個,由一個 列出現「righter」表格,所以當你運行所有四個加入時,你會得到:

t=# select * 
FROM public.brcht 
FULL OUTER JOIN public.cana ON brcht.insee = cana.insee AND brcht.annee = cana.annee 
FULL OUTER JOIN public.font ON cana.insee = font.insee AND cana.annee = font.annee 
FULL OUTER JOIN public.nr ON font.insee = nr.insee AND font.annee = nr.annee 
t-# ; 
insee | annee | nb | insee | annee | nb | insee | annee | nb | insee | annee | nb 
-------+-------+----+--------+-------+----+-------+-------+----+--------+-------+---- 
     |  | | 036223 | 2017 | 1 |  |  | |  |  | 
     |  | | 086001 | 2016 | 2 |  |  | |  |  | 
     |  | |  |  | |  |  | | 036223 | 2013 | 1 
     |  | |  |  | |  |  | | 036223 | 2014 | 1 
     |  | |  |  | |  |  | | 086001 | 2013 | 1 
     |  | |  |  | |  |  | | 086001 | 2014 | 2 
     |  | |  |  | |  |  | | 086001 | 2015 | 4 
     |  | |  |  | |  |  | | 086001 | 2016 | 2 
(8 rows) 

所以第八欄是font.annee(頭腦 - 這是空無處不在) - 你nr.insee加入吧 - 沒有匹配的 - 充滿加入需要從以前的三個表加入所有的行和從nr表中的所有行 - 你得到8行

+0

爲什麼你會加入對''cana' nr'?我不明白加入4張牌桌的方式......在我的例子中,我首先將'brcht'與'cana'結合起來,然後'cana'與'font'結合,然後''font'結合'nr'。我繼續這樣做似乎合乎邏輯。有沒有一種合理的方式將表格連接在一起? – wiltomap

+0

@wiltomap試圖解釋。如果你不使用'()'連接發生從左到右,所以最後的連接加入整個前面的NULL列 - 你從(brcht,cana,font)和all中獲得所有nr(全部 - 因爲它們沒有您用於連接的列上的常見值)。希望它是有道理的 - 解釋不是我最好的技能 –

+0

好吧,我明白了,謝謝!問題是4個表的內容會週期性地改變,所以我不能根據這個來適應連接...我需要一種將表連接在一起的方式,以適應任何表內容。 – wiltomap

0

您將需要在您正在使用的查詢上執行GROUP BY和SUM()bigint列。

select 
    insee, annee 
    , sum(brcht) brcht 
    , sum(cana) cana 
    , sum(font) font 
    , sum(nr) nr 
    , sum(total) total 
from (
    SELECT 
    COALESCE(brcht.insee, cana.insee, font.insee, nr.insee) AS insee, 
    COALESCE(brcht.annee, cana.annee, font.annee, nr.annee) AS annee, 
    COALESCE(brcht.nb,0) AS brcht, 
    COALESCE(cana.nb,0) AS cana, 
    COALESCE(font.nb,0) AS font, 
    COALESCE(nr.nb,0) AS nr, 
    COALESCE(brcht.nb,0) + COALESCE(cana.nb,0) + COALESCE(font.nb,0) + COALESCE(nr.nb,0) AS total 

    FROM public.brcht 
     FULL OUTER JOIN public.cana ON brcht.insee = cana.insee AND brcht.annee = cana.annee 
     FULL OUTER JOIN public.font ON cana.insee = font.insee AND cana.annee = font.annee 
     FULL OUTER JOIN public.nr ON font.insee = nr.insee AND font.annee = nr.annee 
    ) d 
group by 
    insee, annee