2012-07-17 7 views
5

Sto cercando di trovare il primo valore più basso in una tabella e la data in cui si verifica, per ogni utente DISTINCT in una tabella.Recupero del primo valore più basso nella tabella e la data in cui si verifica, per ogni utente distinto

Questo è lo schema della tabella e alcuni dati di esempio:

CREATE TABLE diet_watch (
    entry_date date NOT NULL, 
    user_id int default 1, 
    weight  double precision NOT NULL 
); 

INSERT INTO diet_watch VALUES ('2001-01-01', 1, 128.2); 
INSERT INTO diet_watch VALUES ('2001-01-02', 1, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-03', 1, 122.3); 
INSERT INTO diet_watch VALUES ('2001-01-04', 1, 303.7); 
INSERT INTO diet_watch VALUES ('2001-01-05', 1, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-01', 2, 121.0); 
INSERT INTO diet_watch VALUES ('2001-01-06', 2, 128.0); 

Lo SQL mi è venuta è qui in this snippet

allora ho stato informato che non è corretto, forse qualcuno può spiegare che cosa il problema con il mio SQL è?

Nota: preferirei ANSI SQL se possibile, ma sto utilizzando PostgreSQL, quindi se devo utilizzare un determinato tipo di SQL, deve funzionare su PG.

+0

Non riesco a SQL violino in questo momento. Puoi pubblicare la tua domanda? – RedFilter

+0

@RedFilter - SQL Fiddle non funziona per te? Cosa sta succedendo? –

+0

@JakeFeasel Va bene ora - penso che il server abbia subito un duro colpo, la pagina ha impiegato un paio di minuti per il rendering. Ma era OK dopo. – RedFilter

risposta

6

Nota: Non sono sicuro se funzioni finestra sono ANSI SQL

funzioni finestra sono una parte del SQL: specifica 2003: http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function (Thx @a_horse_with_no_name)

Prova questa:

http://sqlfiddle.com/#!1/7aa4e/22

SELECT * 
    FROM 
    (
    SELECT a.*, 
      ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY weight) AS Position 
     FROM diet_watch a 

    ) a 
    WHERE a.Position = 1 
+0

Sì, le funzioni della finestra ** sono ** ANSI SQL (dal 2003). –

+0

@a_horse_with_no_name Stavo cercando di ottenere un riferimento online per postare qui.Se ne hai una utile puoi postarla? – Chandu

+0

http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function –

1

In primo luogo, la tua richiesta è inutilmente complicata. Puoi semplicemente inserire il gruppo nella subquery ed eliminare la query esterna.

La funzione di Windows, citata da @Chandu, è un'ottima soluzione. È ANSI SQL e postgres lo supporta. Tuttavia, non tutti i database lo fanno. Un'alternativa è:

select dw.* 
from diet_watch dw join 
    (select user_id, min(entry_date) as mindate 
     from diet_watch dw 
     group by user_id 
    ) dwmin 
    on dw.user_id = dwmin.user_id and dw.entry_date = dwmin.mindate 

Il motivo per cui la query originale non funziona è perché la data_introduzione minima potrebbe non avere il peso minimo. La tua query recupera il minimo di ogni campo in modo indipendente. Questa versione trova la data minima, quindi la aggiunge alla tabella originale per ottenere il peso (e altre informazioni) in quel giorno.

+0

In realtà quasi tutti i DBMS supportano le funzioni di windowing. Ci sono solo pochissimi che non lo fanno (in particolare MySQL e SQLite) –

+0

+1, Principalmente per la spiegazione del perché la query OP fallisce – dbenham

1

Se stai cercando la prima volta che ogni utente ha raggiunto il loro peso minimo, penso che funzioni. Vedo nei dati di test, l'utente 1 ottiene il minimo di 121 due volte e vuoi il primo appuntamento? Per quanto ne so, questo dovrebbe funzionare su ogni motore SQL.

SELECT min(dw.entry_date), dw.user_id, dw.weight FROM diet_watch dw, 
    (SELECT min(weight) AS "weight", user_id FROM diet_watch GROUP BY user_id) mins 
WHERE dw.user_id = mins.user_id AND dw.weight = mins.weight 
GROUP BY dw.user_id, dw.weight 

La selezione interna rileva il peso minimo di ciascun utente. Un altro minuto è necessario alla data, perché altrimenti non si selezionerebbe specificamente la prima volta che si raggiungeva il peso minimo per quell'utente.

http://sqlfiddle.com/#!1/7aa4e/51/0

Problemi correlati