5

在 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
4

5 回答 5

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

于 2013-04-24T14:07:23.860 回答
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)
)

您使用嵌套查询和 count(*) 检查先前的查询是否为 NULL。

于 2013-04-24T14:08:00.103 回答
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

于 2013-04-24T14:03:57.307 回答
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)
于 2013-04-24T14:08:05.993 回答
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 ))

但这一定是丑陋而缓慢的。

也许 LEFT JOIN with IS NULL 会比 NOT EXISTS 好

于 2013-04-24T14:17:40.527 回答