2011-11-25 12 views
5

Questi sono i datiSeleziona una riga con valore distinto di una colonna

id name  start_date end_date merchant_id 
=================================================== 
111 name1 25-nov-11 31-jan-12 9999 
222 name2 23-nov-11 25-dec-11 9999 
333 name3 25-nov-11 25-nov-12 9999 
444 name4 20-nov-11 20-nov-11 9999 
555 name5 25-nov-11 25-dec-11 8888 
666 name6 19-oct-11 20-nov-11 8888 
777 name7 20-nov-11 20-jun-12 8888 

devo ottenere tutte le righe filtrate per start_date (desc) dove start_date<=today e end_date >=today ma limite 1 per merchant_id. Il che significa che se la query trova più di una riga, restituisce solo la prima.


script di test

CREATE TABLE DEAL 
(
    ID   VARCHAR2(40 BYTE)  NOT NULL, 
    NAME   VARCHAR2(255 BYTE), 
    START_DATE DATE, 
    END_DATE  DATE, 
    MERCHANT_ID NUMBER(22), 
CONSTRAINT DEAL PRIMARY KEY (ID) 
); 

INSERT ALL 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('111','name1','25-nov-11','31-jan-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('222','name2','23-nov-11','25-dec-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('333','name3','25-nov-11','25-nov-12','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('444','name4','20-nov-11','20-nov-11','9999') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('555','name5','25-nov-11','25-dec-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('666','name6','19-oct-11','20-nov-11','8888') 
INTO DEAL (ID,NAME,START_DATE,END_DATE,MERCHANT_ID) VALUES ('777','name7','20-nov-11','20-jun-12','8888') 
SELECT * FROM dual; 

l'esecuzione di questo:

SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM deal WHERE start_date <= trunc(sysdate) AND end_date >= trunc(sysdate) ORDER BY start_date DESC; 

non restituisce il risultato desiderato come lo stesso ID del commerciante viene restituito più volte:

MERCHANT_ID ID NAME START_DATE END_DATE 
=========================================== 
9999   111 name1 25-NOV-11 31-JAN-12 
9999   333 name3 25-NOV-11 25-NOV-12 
8888   555 name5 25-NOV-11 25-DEC-11 
9999   222 name2 23-NOV-11 25-DEC-11 
8888   777 name7 20-NOV-11 20-JUN-12 
+0

è possibile utilizzare clausola BETWEEN invece di start_date <= oggi e data_finale> = oggi stesso. –

+0

Ho provato varie affermazioni con distinti, limite, gruppo per ... ma non sono riuscito a far funzionare nessuno. Posso ottenere tutte le righe con la data di inizio e di fine appropriata, ma non so come restituire 1 riga per merchant_id –

+0

Quale database stai utilizzando? se si utilizza Oracle, una soluzione utilizza le funzioni analitiche – Giovanni

risposta

2

La seguente query di Oracle dovrebbe fare quello che ti serve:

SELECT * 
FROM (
    SELECT TABLE1.*, DENSE_RANK() OVER(PARTITION BY MERCHANT_ID ORDER BY START_DATE DESC, ID) R 
    FROM TABLE1 
    WHERE SYSDATE BETWEEN START_DATE AND END_DATE 
) 
WHERE R = 1 
ORDER BY START_DATE DESC 

In sostanza, per prima cosa filtra le righe per data e quindi ignora tutte le righe, ma lo è il primo quello che condivide lo stesso MERCHANT_ID.

Si prega di notare che il significato di "primo" è definito rispetto all'ordine START_DATE decrescente. Le due righe hanno lo stesso START_DATE, quindi la "contestazione" viene risolta utilizzando l'ordine ID.

+0

Perfetto! Grazie! –

0

Hi qualcosa di simile potrebbe funzionare:

select id, name,  start_date, end_date from (
select id, name,  start_date, end_date, ROW_NUMBER() 
    OVER (PARTITION BY merchant_id ORDER BY merchant_id) AS rnum from your_table 
    where start_date<=trunc(sysdate) and end_date>=trunc(sysdate)) 
    where rnum=1 
order by start_date desc 

se si fornisce uno script di test semplice per la creazione e il popolamento del tavolo che posso darvi la query corretta.

+0

Script di prova aggiunto al post originale. –

0

A seconda del tipo di sql in esecuzione (mysql, sql server, ecc.) Saranno disponibili risposte alternative.

Per esempio, in SQL Server si potrebbe dire "Assegna ogni riga un numero, a partire da 1 per ogni commerciante", e scegliere sempre il numero 1.

In SQL generica, devi essere un po 'meno diretta . Sembra che la tua colonna ID sia garantita come unica? Se così un modo di formulare la domanda è "ottenere record all'interno dell'intervallo di date DOVE non esiste un ID superiore nello stesso intervallo di date per lo stesso commerciante"

Sai già come filtrare da> e < oggi? Penso che la risposta a come fare che è specifico per il tipo di SQL si sta utilizzando:

in modo da provare:

SELECT * from myFavoriteTable 
    WHERE today() < end_date and today > start_date -- for this date criteria use whatever works 
    AND NOT EXISTS (SELECT * from myFavoriteTable as TooLow 
     WHERE today() < end_date and today() > start_date -- as above 
     AND TooLow.Merchant = myFavoriteTable.merchant 
     AND TooLow.id > myFavoriteTable.id) 
+0

SQL è per Oracle. –

-1

Tutte queste altre risposte sembrano complicate ... È possibile utilizzare il modificatore DISTINCT in Oracle per ottenere una sola riga unica per una colonna specifica. Ecco una domanda che si potrebbe usare per recuperare i dati che si desidera, data la struttura della tabella nel tuo post:

SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM table WHERE start_date >= today AND end_date < today ORDER BY start_date DESC

+0

Questo non restituisce i risultati richiesti SELECT DISTINCT merchant_id, id, name, start_date, end_date FROM deal WHERE start_date <= trunc (sysdate) AND end_date> = trunc (sysdate) ORDINA BY start_date DESC; –

+0

Non restituisce righe distinte per una singola colonna – Sasi

Problemi correlati