2017-08-03 111 views
0

關於查詢PostgreSQL的問題。
存儲過程或任何編程語言內部都很簡單,但我的問題是可以通過一個select語句來完成。這是兩個表格的一個例子。來自多個表的PostgreSQL查詢

enter image description here 謝謝。

+1

你想要的結果是什麼? –

+0

圖像上的第三個輸出 –

+0

如果只是通過存儲過程或在任何編程代碼中,給出一個例子,我們可以幫助將它變成簡單的SELECT語句 - 儘管通常問題是從SELECT語句開始的另一個方向到應用程序語言代碼。 – manassehkatz

回答

0

您通常會在某種報告工具中執行「羣組標題」。但是,如果您願意,它可以在純SQL中完成。

您在「標準JOIN」先從數據:

-- The basic query 
SELECT 
    table_1.table_1_id, phone, name, some_data, 
    row_number() over(partition by table_1.table_1_id order by some_data) 
FROM 
    table_1 
    JOIN table_2 ON table_2.table_1_id = table_1.table_1_id ; 

這將如下表產生:

 
table_1_id | phone | name | some_data | row_number 
---------: | :---- | :--- | :-------- | ---------: 
     1 | 502 | aa | a   |   1 
     1 | 502 | aa | b   |   2 
     1 | 502 | aa | j   |   3 
     1 | 502 | aa | n   |   4 

     2 | 268 | bb | a   |   1 
     2 | 268 | bb | s   |   2 
     2 | 268 | bb | y   |   3 

     5 | 984 | ee | a   |   1 
     5 | 984 | ee | n   |   2 
     5 | 984 | ee | w   |   3 

如果你想添加一些標題行,也不顯示的值phone, name, we need to *add* these data to the query. This is done by making a second specific SELECT for the headers, and UNION ALL`與第一個。

也就是說,我們將使用:

-- This query produces the 'headers' 
SELECT DISTINCT 
    table_1.table_1_id, 
    phone, 
    name, 
    '' AS some_data, 
    true as is_header -- this marks this row as a 'header' 
FROM 
    table_1 
    JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 

UNION ALL 

-- This query produces the actual data 
SELECT 
    table_1.table_1_id, 
    phone, 
    name, 
    some_data, 
    false as is_header 
FROM 
    table_1 
    JOIN table_2 ON table_2.table_1_id = table_1.table_1_id ; 

現在,我們讓這個查詢,並提出一些額外的邏輯來決定哪些數據需要被顯示,並需要隱藏其中一個(實際上,顯示爲 ''):

-- A few tricks to do the formatting 
SELECT 
    -- Here we decide which information to show, which not 
    case when is_header then cast(table_1_id as text) else '' end AS table_1_id, 
    case when is_header then phone     else '' end AS phone, 
    case when is_header then name      else '' end as name, 
    case when is_header then ''      else some_data end as some_data 
FROM 
    (-- This query produces the 'headers' 
    SELECT DISTINCT 
     table_1.table_1_id, 
     phone, 
     name, 
     '' AS some_data, 
     true as is_header -- this marks this row as a 'header 
    FROM 
     table_1 
     JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 
    UNION ALL 
    -- This query produces the actual data 
    SELECT 
     table_1.table_1_id, 
     phone, 
     name, 
     some_data, 
     false as is_header 
    FROM 
     table_1 
     JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 
    ) AS q 
ORDER BY 
    q.table_1_id, is_header DESC /* Header goes first */, some_data ; 

這產生:

 
table_1_id | phone | name | some_data 
:--------- | :---- | :--- | :-------- 
1   | 502 | aa |   
      |  |  | a   
      |  |  | b   
      |  |  | j   
      |  |  | n   
2   | 268 | bb |   
      |  |  | a   
      |  |  | s   
      |  |  | y   
5   | 984 | ee |   
      |  |  | a   
      |  |  | n   
      |  |  | w   

你可以看到整個安裝和模擬數據在dbfiddle here


請注意,您指定的順序不保留。你應該有一些邏輯應該如何訂購。 SQL沒有「插入順序」或「自然順序」的概念;你總是必須選擇你想要的一個(否則,數據庫會選擇它最方便的一個,並且可能從一個執行改變到下一個)。

+0

http://dbfiddle.uk/?rdbms=postgres_9.6&fiddle=159bee342778bfc88a6e138e29f45999 - 查看最後一個查詢。 – Abelisto

+0

@Abelisto:我認爲我們同意:你在顯示空白的位置顯示空串。這只是*介紹*。 – joanolo

+0

這不是關於結果表示,而是關於查詢(似乎你錯過了它)。 – Abelisto

0

有像grouping sets這樣不錯的功能。

使用它你可以在單個查詢/結果集中得到幾組不同的分組條件。感謝例如數據joanolo

讓我們開始在最簡單的查詢:

SELECT 
    table_1.table_1_id, phone, name, some_data 
FROM 
    table_1 JOIN table_2 ON table_2.table_1_id = table_1.table_1_id; 
 
┌────────────┬───────┬──────┬───────────┐ 
│ table_1_id │ phone │ name │ some_data │ 
╞════════════╪═══════╪══════╪═══════════╡ 
│   1 │ 502 │ aa │ a   │ 
│   1 │ 502 │ aa │ b   │ 
│   1 │ 502 │ aa │ n   │ 
│   1 │ 502 │ aa │ j   │ 
│   5 │ 984 │ ee │ w   │ 
│   5 │ 984 │ ee │ a   │ 
│   5 │ 984 │ ee │ n   │ 
│   2 │ 268 │ bb │ s   │ 
│   2 │ 268 │ bb │ a   │ 
│   2 │ 268 │ bb │ y   │ 
└────────────┴───────┴──────┴───────────┘ 

這裏凌晨必要通過前三列添加組:

SELECT 
    table_1.table_1_id, phone, name--, some_data 
FROM 
    table_1 JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 
GROUP BY GROUPING SETS ((table_1.table_1_id, phone, name)); 
 
┌────────────┬───────┬──────┐ 
│ table_1_id │ phone │ name │ 
╞════════════╪═══════╪══════╡ 
│   2 │ 268 │ bb │ 
│   5 │ 984 │ ee │ 
│   1 │ 502 │ aa │ 
└────────────┴───────┴──────┘ 

注意雙括號。實際上它等於簡單的GROUP BY table_1.table_1_id, phone, name(這是因爲我註釋了some_data列,它不在組中)。但是,我們要添加到我們查詢更多資料:

SELECT 
    table_1.table_1_id, phone, name, some_data 
FROM 
    table_1 JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 
GROUP By GROUPING SETS ((table_1.table_1_id, phone, name),(table_1.table_1_id, phone, name, some_data)); 
 
┌────────────┬───────┬──────┬───────────┐ 
│ table_1_id │ phone │ name │ some_data │ 
╞════════════╪═══════╪══════╪═══════════╡ 
│   1 │ 502 │ aa │ a   │ 
│   1 │ 502 │ aa │ b   │ 
│   1 │ 502 │ aa │ j   │ 
│   1 │ 502 │ aa │ n   │ 
│   1 │ 502 │ aa │ ░░░░  │ 
│   2 │ 268 │ bb │ a   │ 
│   2 │ 268 │ bb │ s   │ 
│   2 │ 268 │ bb │ y   │ 
│   2 │ 268 │ bb │ ░░░░  │ 
│   5 │ 984 │ ee │ a   │ 
│   5 │ 984 │ ee │ n   │ 
│   5 │ 984 │ ee │ w   │ 
│   5 │ 984 │ ee │ ░░░░  │ 
└────────────┴───────┴──────┴───────────┘ 

這是我們想要什麼差不多。我們只需要訂購在適當的方式將數據和清理一些列:

SELECT 
    case when some_data is null then table_1.table_1_id end as table_1_id, 
    case when some_data is null then phone end as phone, 
    case when some_data is null then name end as name, 
    some_data 
FROM 
    table_1 
    JOIN table_2 ON table_2.table_1_id = table_1.table_1_id 
group by grouping sets((table_1.table_1_id, phone, name), (table_1.table_1_id, phone, name, some_data)) 
order by table_1.table_1_id, some_data nulls first; 
 
┌────────────┬───────┬──────┬───────────┐ 
│ table_1_id │ phone │ name │ some_data │ 
╞════════════╪═══════╪══════╪═══════════╡ 
│   1 │ 502 │ aa │ ░░░░  │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ a   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ b   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ j   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ n   │ 
│   2 │ 268 │ bb │ ░░░░  │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ a   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ s   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ y   │ 
│   5 │ 984 │ ee │ ░░░░  │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ a   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ n   │ 
│  ░░░░ │ ░░░░ │ ░░░░ │ w   │ 
└────────────┴───────┴──────┴───────────┘ 

賓果!希望這是你要求的。