Seleziona una colonna DISTINCT SQL
-
05-07-2019 - |
Domanda
Aggiunto: lavorare con SQL Server 2000 e 2005, quindi deve funzionare su entrambi. Inoltre, value_rk non è un numero / numero intero (errore: l'identificatore univoco del tipo di dati Operando non è valido per l'operatore minimo)
Esiste un modo per eseguire una singola colonna "DISTINCT" corrispondenza quando non mi importa delle altre colonne restituite? Esempio:
**Table**
Value A, Value L, Value P
Value A, Value Q, Value Z
Devo restituire solo una di queste righe in base a ciò che è nel primo (Valore A). Ho ancora bisogno di risultati dalla seconda e terza colonna (la seconda dovrebbe effettivamente corrispondere a tutti i livelli comunque, ma la terza è una chiave unica, di cui ho bisogno almeno di una).
Ecco cosa ho ottenuto finora, anche se ovviamente non funziona:
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
Sto lavorando in ColdFusion, quindi se c'è una semplice soluzione in ciò sono aperto anche a quello. Sto cercando di limitare o " raggruppare per " la prima colonna "valore". value_rk è il mio grosso problema poiché ogni valore è unico ma ne ho solo bisogno.
NOTA: value_rk non è un numero, quindi NON FUNZIONA
AGGIORNAMENTO: ho una versione funzionante, probabilmente è un po 'più lenta di una versione SQL pura, ma onestamente tutto ciò che funziona a questo punto è meglio di niente. Prende i risultati dalla prima query, esegue una seconda query tranne limitandone i risultati a uno e acquisisce un valore_rk corrispondente per il valore corrispondente. In questo modo:
<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>
...
Quindi il gioco è fatto, selezionando una singola colonna distintamente in ColdFusion. Qualsiasi suggerimento su SQL Server 2000/2005 è ancora molto gradito :)
Soluzione
potrebbe funzionare:
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
.. non testato.
Altri suggerimenti
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;
In altre parole, trova la riga a1
per la quale non esiste alcuna riga a2
con lo stesso valore
e un value_rk maggiore
.
Questo dovrebbe funzionare per PostgreSQL, non so quali dbms usi.
SELECT DISTINCT ON (value)
value,
attribute_definition_id,
value_rk
FROM
attribute_values
ORDER BY
value,
attribute_definition_id
È questo quello che stai cercando?
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
Se value_rk è unico, dovrebbe funzionare.
Ok, ecco i miei presupposti:
SQL Server standard
value_rk non è un valore numerico, ma value e attributo_definizione_id sono numerici.
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)
Se uno di questi campi non è numerico, richiederà più riflessione. Fatecelo sapere.
Se sei aperto all'utilizzo delle variabili di tabella, puoi tenerlo tutto all'interno di una singola chiamata al database in questo modo:
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
Essenzialmente stai creando un recordset limitato con la tabella riempita con valori univoci di 'valore' e lasciando che SQL Server riempia gli spazi usando solo una delle corrispondenze dalla tabella principale.
Modificato per aggiungere: questa sintassi funziona perfettamente con cfquery.
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
NON TESTATO!
Non sono sicuro di comprendere appieno il tuo set-up, ma farei qualcosa del genere:
SELECT value, attribute_definition_id, value_rk
FROM attribute_values
GROUP BY value
ORDER BY attribute_definition_id;
Ancora una volta, non sono sicuro di quale colonna stai cercando di limitare o di come vuoi limitarla.
Meno elegante di quanto vorrei ---- è essenzialmente quello che stai facendo, solo in puro SQL --- ma funziona e può essere fatto tutto in 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
Puoi aggiungere un depVal2 e altri usando questo metodo.
penso
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
lavorato
Come notato da John Fiala, la risposta canonica in SQL Server è quella di utilizzare una clausola group by quando si desidera eseguire un "distinto" operazione su un sottoinsieme di colonne. Perché questa è la risposta canonica corretta? Bene, vuoi inserire colonne che non fanno parte del tuo "distinto" gruppo. Esattamente quali righe vuoi inserire per queste colonne sussidiarie? L'uso di una clausola group by e la definizione di funzioni aggregate per queste colonne sussidiarie rende la tua query ben educata, nel senso che ora sai come si ottengono queste colonne sussidiarie. Questo articolo fornisce maggiori dettagli:
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
Inoltre, vale la pena notare che MIN e MAX funzionano sul testo e su molti altri tipi di dati che non sono valori numerici.