Выпуск PostgreSQL GROUP BY - PullRequest
       35

Выпуск PostgreSQL GROUP BY

0 голосов
/ 08 марта 2012

Предположим, у меня есть таблица

      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

Я хочу удалить дубликаты каналов (строки с одинаковыми именами и номерами). Но я хочу, чтобы результат содержал другие столбцы вместе с именем и номером.

Проблема в том, какие id и address я выбираю, как только удалю дубликаты. Я счастлив выбрать первое, что он найдет. Так, например, результат из приведенной выше таблицы должен быть

      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 (..), но я просто не могу придумать, как это сделать в одном запросе.

Есть идеи?

Ответы [ 4 ]

4 голосов
/ 08 марта 2012
SELECT DISTINCT ON (name,number)
       id,
       name,
       number,
       address
  FROM table
 ORDER BY name,number,id;
0 голосов
/ 08 марта 2012

Я думаю, что наиболее понятный способ сделать это с помощью представлений или общих табличных выражений.Я буду использовать общие табличные выражения.

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 голосов
/ 08 марта 2012

Этого должно быть достаточно:

 SELECT MIN(id), name, number, address FROM table GROUP BY name, number
0 голосов
/ 08 марта 2012
SELECT min(id),
       name,
       number,
       min(address)
FROM the_table
GROUP BY name, number;

Редактировать: Если вам нужно сопоставить идентификатор и адрес, то есть другое решение:

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
...