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


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

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

SELECT DISTINCT field1, * from table
15 300

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

просто включите все ваши поля в предложение 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 из таблицы 1 работает, если значения всех трех столбцов уникальны в таблице.

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