2012-03-08 95 views
0

假設我有表PostgreSQL的GROUP BY問題

 id  |  name  | number |    address 
--------------+------------------+---------+------------------------------------- 
1   | channel A  |  0 | http://stream01 
2   | channel B  |  2 | http://stream02 
3   | channel C  |  16 | http://stream03 
4   | channel B  |  2 | http://stream04 
5   | channel B  |  16 | http://stream05 
6   | channel C  |  16 | http://stream06 
7   | channel A  |  7 | http://stream07 
8   | channel A  |  5 | http://stream08 
9   | channel A  |  0 | http://stream09 
...etc 

我想刪除重複的頻道(行具有相同的名稱和號碼)。但我希望結果包含其他列以及名稱和編號。

問題是我選擇了哪一個idaddress刪除了重複項。我很高興選擇它找到的第一個。因此,舉例來說,從上表的結果應該是

 id  |  name  | number |    address 
--------------+------------------+---------+------------------------------------- 
1   | channel A  |  0 | http://stream01 
2   | channel B  |  2 | http://stream02 
3   | channel C  |  16 | http://stream03 
5   | channel B  |  16 | http://stream05 
7   | channel A  |  7 | http://stream07 
8   | channel A  |  5 | http://stream08 
...etc 

我意識到我可能會在我的查詢需要SELECT name,number FROM table GROUP BY name,number和查詢應該開始SELECT id,name,number,address FROM (..)但我想不出辦法在一個查詢中執行此操作。

任何想法?

+0

隨着「刪除」你的意思是你想刪除行或只是沒有他們的結果? – 2012-03-08 14:08:50

+0

沒有他們的結果。有一種感覺,我幾乎擁有它 - 「SELECT ID,名稱,編號,地址從表AS AS JOIN(選擇名稱,號碼FROM表GROUP BY名稱,編號)AS j USING(name,number)'。沒有工作。 – tbh1 2012-03-08 14:15:19

回答

4
SELECT DISTINCT ON (name,number) 
     id, 
     name, 
     number, 
     address 
    FROM table 
ORDER BY name,number,id; 
+0

謝謝。我今天早些時候嘗試過'DISTINCT ON',但沒有奏效。這是因爲我的實際查詢最後有一個'ORDER BY',並且拋出了錯誤'SELECT DISTINCT ON表達式必須匹配初始的ORDER BY表達式'。我可以通過在'()'中包裝整個查詢並準備結束一個'SELECT * FROM'並在末尾粘貼我的'ORDER BY'來解決這個問題。 – tbh1 2012-03-08 14:52:34

0
SELECT min(id), 
     name, 
     number, 
     min(address) 
FROM the_table 
GROUP BY name, number; 

編輯:
如果您需要匹配的ID和地址,再下面是另一種解決方案:

SELECT id, 
     name, 
     number, 
     address 
FROM ( 
    SELECT id, 
     name, 
     number, 
     address, 
     row_number() over (partition by name, number order by id) as rn 
    FROM the_table 
) t 
WHERE rn = 1 
+0

如果min(id)和min(address)不在同一行,這將會產生一個不在原始表中的行的效果,不是嗎? – 2012-03-08 14:32:05

+0

是的,你是對的。我理解這樣一個問題,即tbh1不關心返回哪個值。 – 2012-03-08 14:49:24

+0

謝謝你。我的實際查詢比問題中的虛擬查詢要複雜得多。在'min()'中包裝所有內容並不意味着我是我的最佳解決方案,但謝謝。 – tbh1 2012-03-08 14:55:10

0

這應該是足夠:

SELECT MIN(id), name, number, address FROM table GROUP BY name, number 
+0

會引發錯誤。您需要在地址上應用集合函數,或者將其包含在GROUP BY子句中 – 2012-03-08 14:22:55

0

我認爲最容易理解的方式就是機智h視圖或通用表格表達式。我將使用公共表格表達式。

create table test (
    id integer primary key, 
    name varchar(20) not null, 
    number integer not null, 
    address varchar(30) not null 
); 

insert into test values 
(1, 'channel A', 0, 'http://stream01'), 
(2, 'channel B', 2, 'http://stream02'), 
(3, 'channel C', 16, 'http://stream03'), 
(4, 'channel B', 2, 'http://stream04'), 
(5, 'channel B', 16, 'http://stream05'), 
(6, 'channel C', 16, 'http://stream06'), 
(7, 'channel A', 7, 'http://stream07'), 
(8, 'channel A', 5, 'http://stream08'), 
(9, 'channel A', 0, 'http://stream09'); 

with unique_name_num as (
    select distinct name, number 
    from test 
), 
min_id as (
    select number, name, min(id) id 
    from test 
    group by number, name 
) 
select t.* 
from test t 
inner join unique_name_num u on u.name = t.name and u.number = t.number 
inner join min_id m on m.number = t.number and m.name = t.name and m.id = t.id 
order by t.name, t.number 
+0

感謝您的時間,非常感謝。 – tbh1 2012-03-08 14:53:13