2008-10-30 19 views
14

Dodano: Praca z SQL Server 2000 i 2005, więc musi działać na obu. Ponadto, wartość_rk nie jest liczbą/liczbą całkowitą (Błąd: Niepoprawny identyfikator typu danych Operand jest nieprawidłowy dla operatora min)Wybierz jedną kolumnę DISTINCT SQL

Czy istnieje sposób na wykonanie pojedynczej kolumny "DISTINCT", gdy nie interesują mnie inne kolumny zwrócone ? Przykład:

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

Muszę zwrócić tylko jeden z tych wierszy na podstawie tego, co jest w pierwszym (wartość A). Nadal potrzebuję wyników z drugiej i trzeciej kolumny (druga powinna w rzeczywistości pasować do całej tablicy, ale trzecia to unikatowy klucz, którego potrzebuję co najmniej jednego z nich).

Oto co mam do tej pory, choć oczywiście nie dział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 

pracuję w ColdFusion więc jeśli jest to proste obejście, że jestem otwarty na to, jak dobrze . Próbuję ograniczyć lub "pogrupować według" pierwszej kolumny "wartość". value_rk jest moim dużym problemem, ponieważ każda wartość jest wyjątkowa, ale potrzebuję tylko jednego.

UWAGA: value_rk nie jest liczbą, stąd ten NIE DZIAŁA

UPDATE: Mam wersję roboczą, to prawdopodobnie trochę wolniej niż czystej wersji SQL, ale szczerze coś działa w tym momencie jest lepsze niż nic. Pobiera wyniki z pierwszego zapytania, wykonuje drugie zapytanie, z wyjątkiem ograniczania wyników do jednego i pobiera pasujący argument value_rk dla pasującej wartości. Tak jak poniżej:

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

Tak więc masz go, wybierając pojedynczą kolumnę wyraźnie w ColdFusion. Wszelkie czyste sugestie programu SQL Server 2000/2005 są nadal mile widziane :)

+0

Czy możesz wyjaśnić, czego potrzebujesz? Dowolny wiersz, ale tylko jeden wiersz na wartość? Wiersz o wartości, która ma maksymalną wartość_rk? Nie jestem pewien, czy rozumiem, co tu robisz. – tvanfosson

+0

> UWAGA: wartość_rk nie jest liczbą, dlatego to NIE DZIAŁA. Nie ma to nic wspólnego z przyczynami niepowodzenia zapytania. Nie wspominałeś o RDBMS, którego używasz, ale w Oracle możesz użyć MAX w kolumnach znaków. –

+0

MS SQL może również używać MAX w kolumnach nieliczbowych. – BradC

Odpowiedz

11

to może działać:

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 

.. nie testowane.

+1

Działa dla MS SQL dla mnie . – Steffen

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 

NIE BADANE!

+0

Moja wina, napisałem bez sprawdzania siebie, zaktualizowałem, że value_rk nie jest liczbą (max/min wygrał ' t pracy na nim) – Organiccat

+0

max/min będzie działać na wartości varchar w SQL2005. Jakiego db używasz? – BradC

+0

Rzeczywiście testowałem w 2005 roku, ale serwer produkcyjny ma 2000. Otrzymuję błąd niezgodności typu danych, gdy próbuję uruchomić min/max na nim (dodany do początku postu OP). – Organiccat

2

Czy tego właśnie szukasz?

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 

Jeśli value_rk jest unikalny, powinno to działać.

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; 

Innymi słowy znaleźć wiersz a1 dla których nie ma rząd a2 z tego samego value i większą value_rk.

+0

To jest świetne rozwiązanie, ponieważ będzie działać z większością (wszystkich?) RDBMS. Byłem zepsuty przez 'DISTINCT ON' PostgreSQL, który jest prosty w pisaniu, ale niestandardowy, a nie zaimplementowany w SQL Server, między innymi – Sam

1

Nie jestem pewien, czy do końca zrozumieć swoją konfigurację, ale coś w tej pracy:

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

Ponownie, nie jestem pewien, które rzeczywistym kolumna to próbujesz ograniczyć lub jak chcesz to ograniczyć.

8

To powinno działać dla PostgreSQL, nie wiem, którego DBM używasz.

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

PostgreSQL Docs

+4

Jedynym problemem jest tutaj, że MS-SQL nie zna DISTINCT ON, tylko DISTINCT we wszystkich wybranych kolumnach ... –

2

Ok, oto moje założenia:

Standardowy SQL Server

value_rk nie jest wartością numeryczną, ale wartości i attribute_definition_id numeryczny.

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) 

Jeśli jedno z tych pól nie jest numeryczne, będzie wymagać więcej uwagi - daj nam znać.

0

Mniej elegancki niż chciałbym ---- to zasadniczo to, co robisz, tylko w czystym SQL --- ale działa i wszystko można zrobić w 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 

Możesz dodać depVal2 i innych przy użyciu tej metody.

2

Jeśli jesteś otwarty na użyciu zmiennych stole, można zachować to wszystko w ramach jednego połączenia bazy danych takie jak to:

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 

Zasadniczo tworzysz ograniczony zestaw rekordów z tabeli wypełnionej unikatowych wartości „wartości ", i pozwalając SQL Server wypełnić luki za pomocą tylko jednego z meczów z głównej tabeli.

Edytowane w celu dodania: ta składnia działa poprawnie w przypadku cfquery.

0

myślę

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 

pracował

0

Jak zauważył John Fiala, odpowiedź kanoniczna w serwerze SQL jest użycie klauzuli GROUP BY, gdy chcesz wykonać „wyraźną” pracę nad podzbioru kolumn. Dlaczego jest to poprawna odpowiedź kanoniczna? Cóż, chcesz pobrać kolumny, które nie są częścią twojej "odrębnej" grupy. Dokładnie jakie wiersze chcesz pobrać dla tych kolumn pomocniczych? Użycie klauzuli group by i zdefiniowanie funkcji agregujących dla tych kolumn pomocniczych powoduje, że twoje zapytanie jest dobrze zachowane w tym sensie, że wiesz już, w jaki sposób uzyskuje się te kolumny pomocnicze. Ten artykuł zawiera więcej szczegółów:

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 

Ponadto, warto zauważyć, że MIN i MAX prace nad tekstem i kilku innych typów danych, które nie są wartości liczbowe.

Powiązane problemy