Выберите один столбец DISTINCT SQL

Добавлено: работа с SQL Server 2000 и 2005, поэтому приходится работать с обоими. Кроме того, value_rk не является числом / целым числом (ошибка: уникальный идентификатор типа данных операнда недействителен для оператора min)

Есть ли способ выполнить сопоставление "DISTINCT" для одного столбца, когда мне не нужны другие возвращенные столбцы? Пример:

**Table**
Value A, Value L, Value P
Value A, Value Q, Value Z

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

Вот что у меня есть, хотя, очевидно, это не работает:

SELECT value, attribute_definition_id, value_rk
FROM attribute_values
WHERE value IN (
    SELECT value, max(value_rk)
    FROM attribute_values
)
ORDER BY attribute_definition_id

Я работаю в ColdFusion, поэтому, если есть простой обходной путь, я тоже открыт для этого. Я пытаюсь ограничить или "сгруппировать" по "значению" первого столбца. value_rk - моя большая проблема, так как каждое значение уникально, а мне нужно только одно.

ПРИМЕЧАНИЕ: value_rk не является числом, поэтому он НЕ РАБОТАЕТ

ОБНОВЛЕНИЕ: у меня есть рабочая версия, она, вероятно, немного медленнее, чем чистая версия SQL, но, честно говоря, все, что работает на данный момент, лучше, чем ничего. Он берет результаты из первого запроса, выполняет второй запрос, за исключением ограничения его результатов одним, и захватывает совпадающее value_rk для значения, которое совпадает. Вот так:

<cfquery name = "queryBaseValues" datasource = "XXX" timeout = "999">
    SELECT DISTINCT value, attribute_definition_id
    FROM attribute_values
    ORDER BY attribute_definition_id
</cfquery>

<cfoutput query = "queryBaseValues">
    <cfquery name = "queryRKValue" datasource = "XXX">
        SELECT TOP 1 value_rk
        FROM attribute_values
        WHERE value = '#queryBaseValues.value#'
    </cfquery>
    <cfset resourceKey = queryRKValue.value_rk>
    ...

Вот и все, выделив отдельный столбец в ColdFusion отдельно. Любые предложения чистого SQL Server 2000/2005 по-прежнему очень приветствуются :)

Можете уточнить, что вам нужно? Любая строка, но только одна строка на значение? Строка со значением с максимальным значением value_rk? Я не уверен, что понимаю, что вы здесь собираетесь.

tvanfosson 30.10.2008 21:49

> ПРИМЕЧАНИЕ: value_rk не является числом, поэтому он НЕ РАБОТАЕТ. Это не имеет ничего общего с тем, почему ваш запрос не выполняется. Вы не упомянули используемую вами СУБД, но в Oracle вы можете использовать MAX для символьных столбцов.

Mark Brady 30.10.2008 21:55

MS SQL также может использовать MAX для нечисловых столбцов.

BradC 30.10.2008 21:56

Если вам наплевать на другие столбцы, какую пользу они вам принесут?

Tom H 30.10.2008 22:00

Столбец value_rk имеет уникальный идентификационный ключ, который ссылается на другую таблицу. Мне нужно одно из тех значений из этой таблицы, которые совпадают. Мне все равно, какой из них, поскольку большинство из них одинаковы, но мне нужен один из них. Иногда один другой или пустой, но это достаточно редко, чтобы не беспокоиться о нем.

Organiccat 30.10.2008 22:01

Использование TOP ненадежно, если вы также не используете ORDER BY. SQL не гарантирует, что строки будут возвращены в любом порядке, если вы не укажете порядок.

Bill Karwin 30.10.2008 22:17

Являются ли value и attribute_definition_id числовыми?

John Fiala 31.10.2008 02:37

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

Tom H 31.10.2008 16:38

К сожалению, не было реального способа определить, какой из них самый старый или самый новый, база данных не была настроена таким образом (у меня не было выбора в этом вопросе). Часть проекта должна была быть сдана вчера, и я закончил ее, что, хотя и не идеально, было лучше, чем вообще не сдавать: /

Organiccat 31.10.2008 17:21
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
14
9
58 571
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

SELECT value, attribute_definition_id, value_rk
FROM attribute_values
WHERE value, value_rk IN (
        SELECT value, max(value_rk)
        FROM attribute_values
        GROUP BY value
)
ORDER BY attribute_definition_id

НЕ ИСПЫТАНО!

Моя ошибка, я опубликовал без тестирования, я обновил, что value_rk не является числом (max / min на нем не сработает)

Organiccat 30.10.2008 21:49

max / min будет работать со значениями varchar в SQL2005. Какой дб вы используете?

BradC 30.10.2008 21:52

Фактически тестируется в 2005 году, но производственный сервер - 2000. Я получаю ошибку несоответствия типа данных при попытке запустить на нем min / max (добавлено в начало сообщения OP).

Organiccat 30.10.2008 21:56

Сообщение OP похоже на ПИН-код или SSN-номер

Mark Brady 30.10.2008 21:58

Он не работает в вашем сценарии, потому что IN ожидает список значений из одного столбца. WHERE foo in (SELECT bar, max (baz) ... неверно, независимо от того, является ли baz числом или нет.

Mark Brady 30.10.2008 22:02

Я попытался переместить максимум из верхнего выбора с тем же результатом. По какой-то причине наличие максимума в части WHERE на самом деле не вызывает ошибки, но в любом случае не влияет на результаты.

Organiccat 30.10.2008 22:14

Это то, что вы ищете?

SELECT value, attribute_definition_id, value_rk
FROM attribute_values av1
WHERE value_rk IN (
        SELECT max(value_rk)
        FROM attribute_values av2
        WHERE av2.value = av1.value
)
ORDER BY attribute_definition_id

Если value_rk уникален, это должно сработать.

SELECT a1.value, a1.attribute_definition_id, a1.value_rk
FROM attribute_values AS a1
  LEFT OUTER JOIN attribute_values AS a2
    ON (a1.value = a2.value AND a1.value_rk < a2.value_rk)
WHERE a2.value IS NULL
ORDER BY a1.attribute_definition_id;

Другими словами, найдите строку a1, для которой не существует строки a2 с таким же value и большим value_rk.

Это отличное решение, потому что оно будет работать с большинством (всеми?) СУБД. Я был избалован PostgreSQL DISTINCT ON, который прост в вводе, но нестандартен и не реализован, среди прочего, в SQL Server.

Sam 30.01.2014 21:38

Я не уверен, что полностью понимаю вашу настройку, но хотел бы что-то вроде этой работы:

SELECT value, attribute_definition_id, value_rk
FROM attribute_values
GROUP BY value
ORDER BY attribute_definition_id;

Опять же, я не совсем уверен, какой столбец вы пытаетесь ограничить или как вы хотите его ограничить.

Это должно работать для PostgreSQL, я не знаю, какие dbms вы используете.

SELECT DISTINCT ON (value)
  value, 
  attribute_definition_id, 
  value_rk
FROM 
  attribute_values
ORDER BY
  value, 
  attribute_definition_id

Документы PostgreSQL

Единственная проблема здесь в том, что MS-SQL не знает DISTINCT ON, только DISTINCT во всех выбранных столбцах ...

Stefan Steiger 08.09.2011 12:25

Хорошо, вот мои предположения:

Стандартный SQL Server

value_rk - это не числовое значение, а числовое значение и идентификатор_определения_атрибута являются.

SELECT value_rk, MIN(value) as value, MIN(attribute_definition_id) as attribute_definition_id
FROM attribute_values
GROUP BY value_rk
ORDER BY MIN(attribute_definition_id)

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

Менее элегантно, чем хотелось бы - по сути, это то, что вы делаете, просто на чистом SQL - но это работает, и все это можно сделать на SQL.

DECLARE @mytable TABLE(mykey NVARCHAR(512), myVal NVARCHAR(512))

DECLARE @keyVal NVARCHAR(512)
DECLARE @depVal NVARCHAR(512)
DECLARE myCursor CURSOR for
   SELECT DISTINCT(value) FROM attribute_values
OPEN myCursor
FETCH NEXT FROM myCursor INTO @keyVal
WHILE @@FETCH_STATUS=0
  BEGIN
     SET @depVal = (SELECT TOP 1 attribute_definition_id FROM attribute_values WHERE VALUE=@keyVal ORDER BY attribute_definition_id)
     INSERT INTO @mytable (mykey, myVal) VALUES (@keyVal, @depVal)
     FETCH NEXT FROM myCursor INTO @keyVal
  END
DEALLOCATE myCursor

SELECT * FROM @mytable

Вы можете добавить depVal2 и другие, используя этот метод.

Ответ принят как подходящий

это может сработать:

SELECT DISTINCT a.value, a.attribute_definition_id, 
  (SELECT TOP 1 value_rk FROM attribute_values WHERE value = a.value) as value_rk
FROM attribute_values as a
ORDER BY attribute_definition_id

.. не испытано.

Если вы открыты для использования табличных переменных, вы можете сохранить все это в рамках одного вызова базы данных следующим образом:

DECLARE @attribute_values TABLE (value int, attribute_definition_id int, value_rk uniqueidentifier)

INSERT INTO @attribute_values (value)
SELECT DISTINCT value FROM attribute_values

UPDATE @attribute_values
SET attribute_definition_id = av2.attribute_definition_id,
    value_rk = av2.value_rk
FROM @attribute_values av1
INNER JOIN attribute_values av2 ON av1.value = av2.value

SELECT value, attribute_definition_id, value_rk FROM @attribute_values

По сути, вы создаете ограниченный набор записей с таблицей, заполненной уникальными значениями 'value', и позволяете SQL Server заполнять пробелы, используя только одно из совпадений из основной таблицы.

Отредактировано для добавления: этот синтаксис отлично работает в cfquery.

Я думаю

SELECT DISTINCT a.value, a.attribute_definition_id, 
(SELECT TOP 1 value_rk FROM attribute_values WHERE value = a.value) as value_rk
FROM attribute_values as a
ORDER BY attribute_definition_id

работал

Как заметил Джон Фиала, канонический ответ на SQL-сервере - использовать предложение group by, когда вы хотите выполнить «отдельную» операцию над подмножеством столбцов. Почему это правильный канонический ответ? Что ж, вы хотите включить столбцы, которые не являются частью вашей «отдельной» группы. Какие именно строки вы хотите включить в эти вспомогательные столбцы? Использование предложения group by и определение агрегатных функций для этих вспомогательных столбцов делает ваш запрос корректным в том смысле, что теперь вы знаете, как получаются эти вспомогательные столбцы. Эта статья дает более подробную информацию:

http://weblogs.sqlteam.com/jeffs/archive/2007/10/12/sql-distinct-group-by.aspx

SELECT value_rk, MIN(value) as value, 
MIN(attribute_definition_id) as attribute_definition_id
FROM attribute_values
GROUP BY value_rk

Также стоит отметить, что MIN и MAX работают с текстом и некоторыми другими типами данных, которые не являются числовыми значениями.

Другие вопросы по теме