SQL / mysql-выберите distinct / UNIQUE, но верните все столбцы?
SELECT DISTINCT field1, field2, field3, ...... FROM table
Я пытаюсь выполнить следующую инструкцию sql, но я хочу, чтобы она возвращала все столбцы, возможно ли это? Что-то вроде:
SELECT DISTINCT field1, * from table
15 ответов:
вы ищете группу по:
select * from table group by field1
который иногда может быть записан с помощью отдельного оператора on:
select distinct on field1 * from table
на большинстве платформ, однако, ни один из вышеперечисленных не будет работать, потому что поведение на других столбцах не определено. (Первый работает в MySQL, если вы используете.)
вы можете выбрать различные поля и придерживаться выбора одной произвольной строки каждый раз.
на некоторых платформах (например, PostgreSQL, Oracle, T-SQL) это можно сделать непосредственно с помощью оконных функций:
select * from ( select *, row_number() over (partition by field1 order by field2) as row_number from table ) as rows where row_number = 1
на других (MySQL, SQLite) вам нужно будет написать подзапросы, которые заставят вас объединить всю таблицу с собой (пример), поэтому не рекомендуется.
из формулировки вашего вопроса я понимаю, что вы хотите выбрать различные значения для данного поля и для каждого такого значения иметь все остальные значения столбцов в той же строке. Большинство СУБД не позволит этого ни с
DISTINCT
, ниGROUP BY
, потому что результат не определен.подумайте об этом так: если ваш
field1
встречается не один раз, какое значениеfield2
будут перечислены (учитывая, что у вас есть то же значение дляfield1
в два ряда, но два различные значенияfield2
в этих двух строках).однако вы можете использовать агрегатные функции (явно для каждого поля, которое вы хотите показать) и использовать
GROUP BY
вместоDISTINCT
:SELECT field1, MAX(field2), COUNT(field3), SUM(field4), .... FROM table GROUP BY field1
Если я правильно понял вашу проблему, это же я просто. Вы хотите иметь возможность ограничить удобство использования DISTINCT указанным полем, а не применять его ко всем данным.
Если вы используете GROUP BY без агрегатной функции, которая когда-либо поле вы группируете по будет ваш отдельный файл.
Если вы сделаете ваш запрос:
SELECT * from table GROUP BY field1;
Он покажет все ваши результаты, основанные на одном экземпляре field1.
например, если вы есть таблица с именем, адресом и городом. Один человек имеет несколько адресов, записанных, но вы просто хотите один адрес для человека, вы можете запросить следующим образом:
SELECT * FROM persons GROUP BY name;
результатом будет то, что только один экземпляр этого имени будет отображаться с его адресом, а другой будет опущен из результирующей таблицы. Внимание: если ваши файлы имеют атомарные значения, такие как firstName, lastName вы хотите сгруппировать по обоим.
SELECT * FROM persons GROUP BY lastName, firstName;
потому что если два человека имеют та же фамилия, и вы только группируете по фамилии, один из этих людей будет опущен из результатов. Вы должны держать эти вещи в поле зрения. Надеюсь, это поможет.
SELECT c2.field1 , field2 FROM (SELECT DISTINCT field1 FROM dbo.TABLE AS C ) AS c1 JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1
это действительно хороший вопрос. Я уже прочитал некоторые полезные ответы здесь, но, вероятно, я могу добавить более точное объяснение.
сокращение количества результатов запроса с помощью оператора GROUP BY легко, если вы не запрашиваете дополнительную информацию. Предположим, у вас есть следующая таблица "местоположения".
--country-- --city-- France Lyon Poland Krakow France Paris France Marseille Italy Milano
сейчас запрос
SELECT country FROM locations GROUP BY country
в результате:
--country-- France Poland Italy
однако, следующие запрос
SELECT country, city FROM locations GROUP BY country
...выдает ошибку в MS SQL, потому что как ваш компьютер может знать, какой из трех французских городов "Лион", "Париж" или "Марсель" вы хотите прочитать в поле справа от "Франция"?
для того, чтобы исправить второй запрос, необходимо добавить эту информацию. Один из способов сделать это-использовать функции MAX() или MIN(), выбирая наибольшее или наименьшее значение среди всех кандидатов. MAX() и MIN () применимы не только к числовым значениям, но также сравните алфавитный порядок строковых значений.
SELECT country, MAX(city) FROM locations GROUP BY country
в результате:
--country-- --city-- France Paris Poland Krakow Italy Milano
или:
SELECT country, MIN(city) FROM locations GROUP BY country
в результате:
--country-- --city-- France Lyon Poland Krakow Italy Milano
эти функции являются хорошим решением, пока вы в порядке с выбором значения из любого конца алфавитного (или числового) порядка. Но что если это не так? Предположим, что вам нужно значение с определенной характеристикой, например, начиная с буквы 'M'. Теперь все становится сложный.
единственное решение, которое я смог найти до сих пор, - это поместить весь ваш запрос в подзапрос и построить дополнительный столбец вне его руками:
SELECT countrylist.*, (SELECT TOP 1 city FROM locations WHERE country = countrylist.country AND city like 'M%' ) FROM (SELECT country FROM locations GROUP BY country) countrylist
в результате:
--country-- --city-- France Marseille Poland NULL Italy Milano
Отличный вопрос @aryaxt -- вы можете сказать, что это был отличный вопрос, потому что вы задали его 5 лет назад, и я наткнулся на него сегодня, пытаясь найти ответ!
Я просто попытался отредактировать принятый ответ, чтобы включить это, но в случае, если мое редактирование не сделает это:
Если ваша таблица не была такой большой, и предполагая, что ваш первичный ключ был автоинкрементным целым числом, вы могли бы сделать что-то вроде этого:
SELECT table.* FROM table --be able to take out dupes later LEFT JOIN ( SELECT field, MAX(id) as id FROM table GROUP BY field ) as noDupes on noDupes.id = table.id WHERE //this will result in only the last instance being seen noDupes.id is not NULL
вы можете сделать это с помощью
WITH
предложения.например:
WITH c AS (SELECT DISTINCT a, b, c FROM tableName) SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c
Это также позволяет выбрать только строки, выбранные в
WITH
запрос предложений.
для SQL Server можно использовать функции dense_rank и дополнительные функции windowing для получения всех строк и столбцов с повторяющимися значениями в указанных столбцах. Вот вам пример...
with t as ( select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6' ), tdr as ( select *, total_dr_rows = count(*) over(partition by dr) from ( select *, dr = dense_rank() over(order by col1, col2, col3), dr_rn = row_number() over(partition by col1, col2, col3 order by other) from t ) x ) select * from tdr where total_dr_rows > 1
это принимает количество строк для каждой отдельной комбинации col1, col2 и col3.
SELECT * FROM tblname GROUP BY duplicate_values ORDER BY ex.VISITED_ON DESC LIMIT 0 , 30
на
ORDER BY
Я только что поставил пример здесь, вы также можете добавить поле ID в этом
Добавить группу по полю, которое вы хотите проверить на наличие дубликатов ваш запрос может выглядеть как
SELECT field1, field2, field3, ...... FROM table GROUP BY field1
поле field1 будет проверено, чтобы исключить дубликаты записей
или вы можете запросить как
SELECT * FROM table GROUP BY field1
дубликаты записей field1 исключаются из SELECT
Я бы предложил использовать
SELECT * from table where field1 in ( select distinct field1 from table )
таким образом, если у вас есть одно и то же значение в field1 в нескольких строках, все записи будут возвращены.