2013-03-10 8 views
15

Mam następujące polecenie wyboru, aby pobrać następny zaplanowany element dla strumienia. Jeśli nie ma zgodnego wiersza, chcę, aby zwrócił wartość domyślną. Oto linia Używam:Zwróć wartość domyślną, jeśli nie znaleziono wierszy.

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 

To powinno chwycić ostatnio zaplanowaną pozycję, ale nie jeśli jest starszy niż 30 minut przed zapytania. Jeśli jednak użytkownik niczego nie planuje, chcę mieć wartość domyślną, aby coś faktycznie było odtwarzane w strumieniu. Próbowałem następujące:

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

oraz:

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

Jednak zawsze zwraca pusty wynik, jeśli nie zostaną znalezione żadne wiersze. Jak mogę zamiast tego zwrócić wartość domyślną?

Odpowiedz

20

Jednym ze sposobów, aby to zrobić

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 

Ponieważ zwróci tylko jeden wiersz, można użyć funkcję zbiorczą, w tym przypadku MIN(), który gwarantuje, że dostaniesz NULL jeśli wybrane żadne zapisy. Następnie wykona on zadanie: IFNULL() lub .

+1

Wspaniałe rzeczy! Ale w jaki sposób można zastosować tę koncepcję do zapytania zwracającego wiele wierszy zamiast jednego, jak w naszym przypadku? – Vectoria

+0

To naprawdę nie jest dobre rozwiązanie, jak wyjaśnia Tomas poniżej (chyba, że ​​zapytanie o wartość klucza podstawowego). – Pierre

0

Aby obsłużyć większą liczbę przypadków, potrzebna jest pewna logika warunkowa. Funkcja ta jest dostępna tylko w procedurach przechowywanych w MySQL tak trzeba zawinąć ten kod w procedurze i nazywają go:

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

W przypadkach, gdzie jest tylko jeden wiersz oczekiwanych rezultatów, wystarczy użyć UNION o wartości zakodowanego na stałe (s) w drugiej klauzuli SELECT, która ma taką samą liczbę kolumn co oryginalny SELECT.

Dla 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; 

Blokowanie błędów składniowych, wynikiem będzie służyć jeden wiersz w kolumnie o nazwie file.


W bardziej ogólnym przykład:

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

W obu przypadkach:

  • Jeżeli nie znajduje się w pierwszym SELECT ma rzędy, wynikiem będzie wypełniana wartości z drugiego SELECT.

  • Jeśli jeden wiersz zostanie znaleziony w pierwszym SELECT, pierwsze wartości SELECT są dostępne w zestawie wyników, a drugie wartości SELECT są pomijane.

* Nie trzeba przypisać kolumnie Nazwa/alias do drugiej wartości wybrać, czy chcesz korzystać z tych samych kolumn (w tej samej kolejności) z pierwszego SELECT.

* UNION nie wymaga, aby nazwy kolumn z dwóch zjednoczonych zapytań były identyczne, w rzeczywistości można przypisać różne nazwy kolumn do drugiego zapytania SELECT, jeśli pomaga to twojemu przypadkowi. (Kod przetwarzania zestawu wyników będzie musiał uwzględniać różnice w nazewnictwie kolumn.)

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

Uważam, że jest to bardzo łatwe do odczytania i nie wydaje się być pytaniem podatkowym.

+0

To działa bardzo dobrze dla mnie. Musiałem wykonać agregację ('MAX') z predykatem i gdyby nie było wierszy zgodnych z predykatem, nie otrzymałbym żadnych wierszy zwróconych. Teraz otrzymuję zamiast tego domyślną wartość. – Rob

Powiązane problemy