Добавлено: работа с 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 не является числом, поэтому он НЕ РАБОТАЕТ. Это не имеет ничего общего с тем, почему ваш запрос не выполняется. Вы не упомянули используемую вами СУБД, но в Oracle вы можете использовать MAX для символьных столбцов.
MS SQL также может использовать MAX для нечисловых столбцов.
Если вам наплевать на другие столбцы, какую пользу они вам принесут?
Столбец value_rk имеет уникальный идентификационный ключ, который ссылается на другую таблицу. Мне нужно одно из тех значений из этой таблицы, которые совпадают. Мне все равно, какой из них, поскольку большинство из них одинаковы, но мне нужен один из них. Иногда один другой или пустой, но это достаточно редко, чтобы не беспокоиться о нем.
Использование TOP ненадежно, если вы также не используете ORDER BY. SQL не гарантирует, что строки будут возвращены в любом порядке, если вы не укажете порядок.
Являются ли value и attribute_definition_id числовыми?
Я по-прежнему считаю, что вам следовало определить правила относительно того, какие ценности вы хотите. Я всегда с подозрением отношусь к тому, что кто-то говорит мне, что им "все равно", какой ряд они получат. Если вам не нужны пробелы, вам следует запрограммировать это. Если вы хотите самую старую или самую свежую версию, вам следует ее приобрести.
К сожалению, не было реального способа определить, какой из них самый старый или самый новый, база данных не была настроена таким образом (у меня не было выбора в этом вопросе). Часть проекта должна была быть сдана вчера, и я закончил ее, что, хотя и не идеально, было лучше, чем вообще не сдавать: /


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 на нем не сработает)
max / min будет работать со значениями varchar в SQL2005. Какой дб вы используете?
Фактически тестируется в 2005 году, но производственный сервер - 2000. Я получаю ошибку несоответствия типа данных при попытке запустить на нем min / max (добавлено в начало сообщения OP).
Сообщение OP похоже на ПИН-код или SSN-номер
Он не работает в вашем сценарии, потому что IN ожидает список значений из одного столбца. WHERE foo in (SELECT bar, max (baz) ... неверно, независимо от того, является ли baz числом или нет.
Я попытался переместить максимум из верхнего выбора с тем же результатом. По какой-то причине наличие максимума в части WHERE на самом деле не вызывает ошибки, но в любом случае не влияет на результаты.
Это то, что вы ищете?
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.
Я не уверен, что полностью понимаю вашу настройку, но хотел бы что-то вроде этой работы:
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
Единственная проблема здесь в том, что MS-SQL не знает DISTINCT ON, только DISTINCT во всех выбранных столбцах ...
Хорошо, вот мои предположения:
Стандартный 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 работают с текстом и некоторыми другими типами данных, которые не являются числовыми значениями.
Можете уточнить, что вам нужно? Любая строка, но только одна строка на значение? Строка со значением с максимальным значением value_rk? Я не уверен, что понимаю, что вы здесь собираетесь.