2008-10-30 2 views
14

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

Есть ли способ сделать один столбец «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 не является числом, следовательно, это НЕ РАБОТАЕТ

UPDATE: У меня есть рабочий вариант, это, вероятно, совсем немного медленнее, чем чистый SQL версии, но если честно ничего работать в этой точке лучше ничего. Он принимает результаты первого запроса, выполняет второй запрос, кроме ограничения его результатов, и захватывает соответствующее значение_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 по-прежнему очень приветствуются :)

+0

Выясняете, что вам нужно? Любая строка, но только одна строка за значение? Строка со значением, которое имеет максимальное значение_rk? Я не уверен, что понимаю, что вы здесь делаете. – tvanfosson 2008-10-30 18:49:10

+0

> ПРИМЕЧАНИЕ: значение_rk не является числом, поэтому это НЕ РАБОТАЕТ. Это не имеет никакого отношения к тому, почему ваш запрос не удается. Вы не упомянули используемую СУБД, но в Oracle вы можете использовать MAX для столбцов символов. – 2008-10-30 18:55:31

+0

MS SQL также может использовать MAX для нечисловых столбцов. – BradC 2008-10-30 18:56:51

ответ

11

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

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 

.. не тестировалась.

1
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 

НЕ ИСПЫТАНО!

2

Вы хотите что-то ищите?

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 

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

8
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.

1

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

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

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

8

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

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

PostgreSQL Docs

2

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

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

value_rk не является числовым значением, но значение и attribute_definition_id являются числовыми.

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) 

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

0

Менее элегантный, чем мне хотелось бы ---- это, по сути, то, что вы делаете, только в чистом 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 [email protected] 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 и другие, используя этот метод.

2

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

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 

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

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

0

я думаю

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 

работал

0

Как отмечает Джон Фиала, канонический ответ на сервер SQL, чтобы использовать группу пунктом, если вы хотите, чтобы выполнить «отчетливый» операцию над подмножеством столбцов. Почему это правильный канонический ответ? Ну, вы хотите вытащить столбцы, которые не являются частью вашей «отличной» группы. Точно, какие строки вы хотите использовать для этих вспомогательных столбцов? Использование предложения 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 работа над текстом и несколько других типов данных, которые не являются числовые значения.