Domanda

Ho bisogno di recuperare tutte le righe da una tabella di 2 colonne combinato sono tutti diversi.Quindi voglio che tutte le vendite che non hanno altro di vendite che è avvenuto nello stesso giorno per lo stesso prezzo.Le vendite che sono uniche in base al giorno e il prezzo sarà aggiornata per uno stato attivo.

Così sto pensando che:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

Ma il mio cervello fa male andare più in là di questo.

È stato utile?

Soluzione

SELECT DISTINCT a,b,c FROM t

è circa equivalente a:

SELECT a,b,c FROM t GROUP BY a,b,c

E ' una buona idea per ottenere utilizzato per il GRUPPO di sintassi, come è più potente.

Per la query, mi piacerebbe farlo come questo:

UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
    SELECT id
    FROM sales S
    INNER JOIN
    (
        SELECT saleprice, saledate
        FROM sales
        GROUP BY saleprice, saledate
        HAVING COUNT(*) = 1 
    ) T
    ON S.saleprice=T.saleprice AND s.saledate=T.saledate
 )

Altri suggerimenti

Se si mettono insieme le risposte finora, di pulizia e di migliorare, si dovrebbe arrivare a questo superiore query:

UPDATE sales
SET    status = 'ACTIVE'
WHERE  (saleprice, saledate) IN (
    SELECT saleprice, saledate
    FROM   sales
    GROUP  BY saleprice, saledate
    HAVING count(*) = 1 
    );

Che è molto più veloce di uno di loro.Le armi nucleari le prestazioni attualmente accettato di rispondere con un fattore di 10 - 15 (i miei test su PostgreSQL 8.4 e 9.1).

Ma questo è ancora lontana dall'essere ottimale.Utilizzare un NOT EXISTS (anti-)semi-join per prestazioni ancora migliori. EXISTS è standard SQL, è stato intorno per sempre (almeno dal PostgreSQL 7.2, molto prima di questa domanda) e si adatta presentato perfettamente ai requisiti di:

UPDATE sales s
SET    status = 'ACTIVE'
WHERE  NOT EXISTS (
   SELECT FROM sales s1                     -- SELECT list can be empty for EXISTS
   WHERE  s.saleprice = s1.saleprice
   AND    s.saledate  = s1.saledate
   AND    s.id <> s1.id                     -- except for row itself
   )
AND    s.status IS DISTINCT FROM 'ACTIVE';  -- avoid empty updates. see below

db<>violino qui
Vecchio SQL Violino

Unica chiave per identificare la riga

Se non si dispone di una chiave primaria o univoca per la tabella (id nell'esempio), si può sostituire con la colonna di sistema ctid lo scopo di questa query (ma non per altri scopi):

   AND    s1.ctid <> s.ctid

Ogni tabella deve avere una chiave primaria.Aggiungere uno se non avete uno, di sicurezza.Suggerisco un serial o un IDENTITY colonna in Postgres 10+.

Related:

Come è il più veloce?

La subquery nella EXISTS anti-semi-join è possibile arrestare la valutazione non appena il primo ingannare trovato nessun punto in cerca di più).Per una tabella di base con alcuni duplicati questa è solo leggermente più efficiente.Con un sacco di duplicati questo diventa modo più efficiente.

Escludere vuoto aggiornamenti

Per le righe che già hanno status = 'ACTIVE' questo aggiornamento non sarebbe cambiato nulla, ma comunque inserire una nuova riga versione a costo pieno (minori, salvo eccezioni).Normalmente, non si vuole questo.Aggiungere un altro WHERE condizione come dimostrato sopra per evitare questo e per rendere ancora più veloce:

Se status è definito NOT NULL, si può semplificare a:

AND status <> 'ACTIVE';

Sottile differenza nella gestione dei valori NULL

Questa query (a differenza di attualmente accettato risposta da Joel) non considerare i valori NULL uguali.Le seguenti due righe per (saleprice, saledate) potrebbe qualificarsi come "distinti" (anche se cercando identico all'occhio umano):

(123, NULL)
(123, NULL)

Passa anche in un indice univoco e quasi qualsiasi altro luogo, poiché i valori NULL non uguali, secondo lo standard SQL.Vedere:

OTOH, GROUP BY, DISTINCT o DISTINCT ON () il trattamento di valori NULL uguali.Utilizzare una query appropriata stile a seconda di ciò che si desidera raggiungere.È ancora possibile utilizzare questa query, più rapido con IS NOT DISTINCT FROM invece di = per qualsiasi o tutti i confronti a fare nulla uguali.Di più:

Se tutte le colonne sono confrontati definito NOT NULL, non c'è spazio per il dissenso.

Il problema con la query è che quando si utilizza una clausola GROUP BY (che è essenzialmente tramite la distinta) è possibile utilizzare solo le colonne di gruppo o funzioni di aggregazione.Non è possibile utilizzare la colonna id, perché ci sono potenzialmente valori diversi.Nel tuo caso c'è sempre un solo valore a causa della clausola HAVING, ma la maggior parte RDBMS non sono abbastanza intelligente da riconoscere che.

Questo dovrebbe funzionare, tuttavia, (e non ha bisogno di un join):

UPDATE sales
SET status='ACTIVE'
WHERE id IN (
  SELECT MIN(id) FROM sales
  GROUP BY saleprice, saledate
  HAVING COUNT(id) = 1
)

Si potrebbe anche usare MAX o AVG invece di MIN, è importante usare una funzione che restituisce il valore della colonna, se c'è solo una riga corrispondente.

Voglio selezionare i valori distinti da una colonna 'GrondOfLucht', ma devono essere ordinati in ordine come indicato nella colonna "sortering'.Non riesco a diversi valori di una colonna, utilizzando

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

Si darà anche la colonna 'sortering" e perché "GrondOfLucht' E 'sortering' non è univoco, il risultato sarà di TUTTE le righe.

utilizzare il GRUPPO per selezionare i record di 'GrondOfLucht', nell'ordine, da 'sortering

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)

Se il DBMS non supporta distinti con più colonne come questo:

select distinct(col1, col2) from table

Multi selezionare, in generale, può essere eseguita in modo sicuro come segue:

select distinct * from (select col1, col2 from table ) as x

Come questo può funzionare sulla maggior parte dei DBMS e questo dovrebbe essere più veloce di un gruppo da una soluzione come si sta evitando la funzionalità di raggruppamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top