SQL / mysql-выберите distinct / UNIQUE, но верните все столбцы?

SELECT DISTINCT field1, field2, field3, ......   FROM table

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

SELECT DISTINCT field1, * from table

15 ответов


вы ищете группу по:

select *
from table
group by field1

который иногда может быть написан с отдельным утверждением:

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


из формулировки вашего вопроса я понимаю, что вы хотите выбрать различные значения для данного поля и для каждого такого значения иметь все остальные значения столбцов в той же строке. Большинство DBMSs не позволит этого ни с 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 и дополнительные окна, чтобы получить все строки и столбцы с дублированными значениями в указанных столбцах. Вот пример...

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 в этом


добавить GROUP BY в поле, которое вы хотите проверить на наличие дубликатов ваш запрос может выглядеть как

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 в нескольких строках, все записи будут возвращены.


просто включите все свои поля в предложение GROUP BY.


Это можно сделать с помощью внутреннего запроса

$query = "SELECT * 
            FROM (SELECT field
                FROM table
                ORDER BY id DESC) as rows               
            GROUP BY field";

SELECT * from table where field in (SELECT distinct field from table)

выберите DISTINCT FIELD1, FIELD2, FIELD3 из TABLE1 работает, если значения всех трех столбцов уникальны в таблице.

Если, например, у вас есть несколько одинаковых значений для имени, но фамилия и другая информация в выбранных столбцах разные, запись будет включена в результирующий набор.