2013-04-24 90 views
5

在mysql中的一個查詢中做到這一點的最佳方法是什麼?另一個WHERE子句,如果沒有結果

SELECT * FROM products WHERE language = 1 

如果沒有結果

SELECT * FROM products WHERE language = 2 AND country = 1 

如果沒有結果

SELECT * FROM products WHERE language = 2 AND country = 2 
+0

什麼專欄是'*'? – Kermit 2013-04-24 14:00:38

+0

這不是MySQL中的一個查詢,不幸的是:您期望從中得到什麼 – gbn 2013-04-24 14:02:12

+0

我認爲您可以通過ORDER – lvil 2013-04-24 14:03:02

回答

7

我已經編輯它使其工作,但它不再優雅。


原來的(沒有最後一個也沒有)存在缺陷。

原來,這並不像我想象的那麼聰明。見下面的評論。如果第一個和第三個查詢返回數據,它將失敗。如果你只有一個聯盟,但不是兩個或更多聯盟,它確實有效。


這是很容易在MySQL:

select SQL_CALC_FOUND_ROWS * from products where language = 1 
union 
SELECT * FROM products WHERE language = 2 AND country = 1 and found_rows()=0 
union 
SELECT * FROM products WHERE language = 2 AND country = 2 and found_rows()=0 
AND not exists(select * from products where language = 1) 

見FOUND_ROWS的討論()和SQL_CALC_FOUND_ROWS這裏: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows

+1

你可以依賴UNION語句中的found_rows嗎? – gbn 2013-04-24 14:08:54

+0

+1這個想法! :) – biziclop 2013-04-24 14:09:18

+0

@gbn你可以,如果你不使用LIMIT任何地方,並檢查0. – 2013-04-24 14:10:18

1

的MySQL缺乏的功能,以使這一個去
例子:DENSE_RANK窗函數,或TOP..WITH TIES

因此,而不使用臨時表或IF語句(無論如何需要MySQL中的存儲過程),然後在客戶端上將其過濾爲最低優先級值。也就是說,消耗行直到數值發生變化

SELECT *, 1 AS priority FROM products WHERE language = 1 
UNION ALL 
SELECT *, 2 AS priority FROM products WHERE language = 2 AND country = 1 
UNION ALL 
SELECT *, 3 AS priority FROM products WHERE language = 2 AND country = 2 
ORDER BY priority; 

即使不理想,這也會消除往返於MySQL服務器的往返行程。它也避免了重新評估EXISTS子句中的先前SELECTs

+0

你可以做一個單一的選擇,如果你評估優先級作爲一種情況下的條件 - 類似'case語言1時1當2則語言+國家其他4結束'。 – 2013-04-24 14:41:08

2

您可以使用類似以下內容:(編輯使用exists並根據評論限制)。

(
SELECT * FROM products WHERE language = 1 
) 
UNION 
(
SELECT * FROM products WHERE language = 2 AND country = 1 
AND NOT EXISTS(SELECT count(*) FROM products WHERE language = 1 limit 1) 
) 
UNION 
(
SELECT * FROM products WHERE language = 2 AND country = 2 
AND NOT EXISTS(SELECT count(*) FROM products WHERE language = 2 AND country = 1 limit 1) 
AND NOT EXISTS(SELECT count(*) FROM products WHERE language = 1 limit 1) 
) 

您使用嵌套查詢和計數(*)檢查以前的查詢是否爲NULL。

+2

使用不存在可能比檢查0計數好。 – 2013-04-24 14:17:32

+0

@ShawnBalestracci將這些子查詢(COUNT或EXISTS - 無所謂)在每一行上重新執行?也許離開加入+檢查空將是更好的方法? – 2013-04-24 14:19:24

+0

我有一種強烈的感覺,優化器計算出最佳分支,並僅對其進行一次預先計算。這就是SQL引擎的原因:)。 – 2013-04-24 14:21:57

1

嘗試:

select p.* 
from (select min(language) minlang, min(country) minctry 
     from products where language = 1 or 
          (language = 2 and country in (1,2))) c 
join products p 
on p.language = c.minlang and (c.minlang=1 or p.country=c.minctry) 
1

似乎有沒有什麼好辦法,如果可能的話,你最好把它變成一個過程,無論是填充臨時表或返回RowSet對象的客戶端

如何永遠如果沒有可能,你似乎有限制二級和三級查詢:

SELECT * FROM products WHERE language = 1 

UNION ALL 

SELECT * FROM products WHERE language = 2 AND country = 1 
    AND NOT EXISTS (SELECT * FROM products WHERE language = 1) 

UNION ALL 

SELECT * FROM products WHERE language = 2 AND country = 2 
    AND NOT EXISTS (SELECT * FROM products WHERE language = 1 OR (language = 2 AND country = 1)) 

但這只是醜陋和緩慢。

也許與IS NULL左加入會比不存在,雖然

相關問題