在mysql的一个查询中执行此操作的最佳方法是什么?
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 :(得分: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 :(得分:2)
您可以使用以下内容:(根据评论编辑使用EXISTS和LIMIT)。
(
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 :(得分: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子句中以前的SELECT
答案 3 :(得分: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)
答案 4 :(得分: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的LEFT JOIN可能比NOT EXISTS更好