Не более N строк из каждой группы - PullRequest
3 голосов
/ 02 декабря 2011

У меня есть таблица SQL, содержащая информацию о клиенте (назовем ее CustomerDB), включая столбец адреса. Многие из строк в этой таблице имеют точные повторяющиеся адреса. Бизнес-требование состоит в том, чтобы извлечь строки из базы данных так, чтобы:

  • Если имеется более трех точных дубликатов, возьмите только три (игнорируйте остальные)
  • Какие три не важны; подойдут любые три (это не обязательно «первые три»).

Итак, если у меня есть такой набор данных (я также ввел это в проводнике данных , чтобы было проще проверять запросы):

ID     NAME       COMPANY    ADDR1
16242  TOM E      Company A  101 First RD  
16241  RONALD J   Company B  12 Tenth AVE  
16235  KENNETH H             12 Tenth AVE  
16238  MICHAEL H  Company C  12 Tenth AVE  
16243  ANTONIO D  Company D  264 Long ST STE 5  
16237  MICHAEL B  Company E  264 Long ST STE 5  
16234  WALTER L   Company F  73 North RD  
16236  CARL O     Company G  73 North RD  
16239  MICHAEL S  Company H  73 North RD  
16240  MICHAEL I  Company I  73 North RD 

Я хотел бы получить все эти строки, кроме одной из записей "73 North RD". Я надеюсь, что здесь есть какой-то смысл.

Мой ум не очень хорошо работает в операциях на основе множеств, поэтому я не понимаю, как это сделать. Я бы предпочел решение с объяснением , почему это работает. Поскольку я бы хотел, чтобы, так сказать, "научили ловить рыбу" =)

Дополнительная информация:

  • ID - это первичный ключ int (с автоинкрементом)
  • Все остальные столбцы являются текстовыми.
  • Иногда я получаю эти наборы данных как базы данных Access, иногда они находятся в SQL Server. Итак, я бы предпочел решение, которое работает в обоих (то есть не использует CROSS APPLY или CTE)

1 Ответ

3 голосов
/ 02 декабря 2011

Возможное решение может быть

SELECT c1.id, c1.name, c1.company, c1.addr1
FROM CustomerDB c1 LEFT JOIN CustomerDB c2
    ON (c1.addr1 = c2.addr1 and c1.id >= c2.id)
GROUP BY c1.addr1, c1.id, c1.name, c1.company
HAVING COUNT(*) <= 3​

Волшебство (хорошее определение, которое вы дали) сделано GROUP BY ... HAVING ... part.
Конечно, вы знаете, WHERE используется для фильтрации данных при выборе; ну, HAVING используется вместе с GROUP BY для фильтрации сгруппированных данных (то есть после группировки).
Поэтому я сначала группирую данные (порядок важен) по адресу, а затем ограничиваю количество для каждой группы тремя.
Теперь давайте поговорим о внутренней части (вы не спрашивали об этом, но я подумал, что было бы хорошо предоставить вам полный пример).
Часть ON используется для указания движку, какие поля должны использоваться для объединения таблиц; здесь я сопоставляю таблицы по адресу, а затем беру записи с более высоким идентификатором (так, сортировка по возрастанию).

...