2013-03-10 10 views
15

Ho la seguente istruzione select, per prendere il prossimo elemento pianificato per uno stream. Se non c'è una riga corrispondente, voglio che restituisca un valore predefinito. Ecco la linea che sto usando:Restituisce un valore predefinito se non è stata trovata alcuna riga

SELECT `file` FROM `show`, `schedule` 
    WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
    ORDER BY `start_time` DESC LIMIT 1 

Questo dovrebbe afferrare l'elemento più recente in programma, ma non se si tratta di più di 30 minuti prima che la query. Tuttavia, se l'utente non pianifica nulla, desidero un valore predefinito, in modo che qualcosa venga effettivamente riprodotto nello stream. Ho provato la seguente:

SELECT COALESCE(`file`, 'default.webm') FROM `show`, `schedule`... 

E:

SELECT IFNULL(`file`, 'default.webm') FROM `show`, `schedule` 

Tuttavia, restituisce sempre un risultato vuoto se non si trovano le righe. Come posso invece restituire un valore predefinito?

risposta

20

Un modo per farlo

SELECT IFNULL(MIN(`file`), 'default.webm') `file` 
    FROM `show`, `schedule` 
WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
ORDER BY `start_time` DESC LIMIT 1 

Dal momento che ritorni solo una riga, è possibile utilizzare una funzione di aggregazione, in quel caso MIN(), che assicura che si otterrà NULL se nessun record selezionato. Quindi IFNULL() o COALESCE() farà il suo lavoro.

+1

Brilliant Stuff! Ma come può essere applicato questo concetto a una query che restituisce più righe anziché una come nel nostro caso? – Vectoria

+0

Questa non è davvero una buona soluzione come spiega in seguito Tomas (eccetto probabilmente se si esegue una query su un valore di chiave primaria). – Pierre

0

Per gestire una più ampia varietà di casi, è necessaria una logica condizionale. Questo è disponibile solo in stored procedure in MySQL in modo avrete bisogno di avvolgere questo codice in una procedura e chiamarla:

if exists (
     SELECT `file` FROM `show`, `schedule` 
     WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
     AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
) then 
     SELECT `file` FROM `show`, `schedule` 
     WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
     AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
     ORDER BY `start_time` DESC LIMIT 1 
; else 
     select `DefaultValue` as `file` 
; end if 
7

Per i casi in cui si prevede che una sola fila di risultati, basta usare UNION con un valore predefinito (s) in una seconda clausola SELECT con lo stesso numero di colonne della SELECT originale.

Per la OP:

(SELECT `file` FROM `show`, `schedule` 
    WHERE `channel` = 1 AND `start_time` <= UNIX_TIMESTAMP() 
    AND `start_time` > UNIX_TIMESTAMP()-1800 AND `show`.`id` = `schedule`.`file` 
    ORDER BY `start_time` DESC LIMIT 1) UNION (SELECT 'default.webm') LIMIT 1; 

A meno di errori di sintassi, il set di risultati servirà su di una riga con una colonna denominata file.


Come esempio più generale:

(SELECT Col1,Col2,Col3 FROM ExampleTable WHERE ID='1234') 
UNION (SELECT 'Def Val','none','') LIMIT 1; 

In entrambi i casi:

  • Se non sono presenti righe presenti nella prima SELECT, il set di risultati sarà riempito con il valori dal secondo SELEZIONA.

  • Se una prima riga viene trovata nella prima SELECT, i primi valori SELECT vengono offerti nel set di risultati e i secondi valori SELECT vengono omessi.

* Non è necessario assegnare una colonna nome/alias per i secondi valori selezionare se si desidera utilizzare le stesse colonne (nello stesso ordine) dal primo SELECT.

* UNION non richiede che i nomi di colonna delle due query unite siano identici, infatti è possibile assegnare nomi di colonne diversi alla seconda query SELECT se aiuta il caso. (Il codice di elaborazione del set di risultati dovrà contenere le differenze di denominazione delle colonne.)

(SELECT Col1,Col2,Col3 FROM ExampleTable WHERE ID='1234') 
UNION (SELECT 'Def Val' AS `Fallback1`,'none' AS `Fallback2`,'' AS `Fallback3`) LIMIT 1; 

La mia opinione è che questo è molto facile da leggere e non sembra come una query tassazione.

+0

Questo funziona molto bene per me. Avevo bisogno di fare un aggregato ('MAX') con un predicato e se non ci fossero state righe corrispondenti al predicato, non avrei ottenuto il ritorno di righe. Ora ho invece ripristinato il valore predefinito. – Rob

Problemi correlati