【问题标题】:Force MySQL to return a result for all option within IN强制 MySQL 返回 IN 中所有选项的结果
【发布时间】:2013-11-15 15:42:22
【问题描述】:

我有一个简单的 MySQL 语句:

SELECT q1, COUNT(q1) FROM results WHERE q1 IN ('1','2','3');

目前只有 1 和 3 的结果 - 结果是:

1 = 6
3 = 7

但我需要让 MySQL 带回 1,2 和 3 的结果,即使 2 没有数据,如下所示:

1 = 6
2 = 0
3 = 7

有什么想法吗?

【问题讨论】:

  • 你的代码不能假设如果它不在数据集中它是零吗?
  • 不知道如何将结果带回数组并强制代码找出差距所在。

标签: mysql count return return-value


【解决方案1】:

这很棘手,因为没有行与您的值匹配 (2),它们无法计数。

我会通过创建一个包含我想要计数的值列表的临时表来解决这个问题:

CREATE TEMPORARY TABLE q ( q1 INT PRIMARY KEY );
INSERT INTO q (q1) VALUES (1), (2), (3);

然后对结果表执行 OUTER JOIN:

SELECT q.q1, COALESCE(COUNT(*), 0) AS count
FROM q LEFT OUTER JOIN results USING (q1)
GROUP BY q.q1;

这样每个值都将成为最终结果集的一部分,即使它没有匹配的行。


@Mike Christensen 的回复评论:

MySQL 不支持 CTE,尽管它早在 2006 年就被要求:http://bugs.mysql.com/bug.php?id=16244

您可以对派生表做同样的事情:

SELECT q.q1, COALESCE(COUNT(*), 0) AS count
FROM (SELECT 1 AS q1 UNION ALL SELECT 2 UNION ALL SELECT 3) AS q 
LEFT OUTER JOIN results USING (q1)
GROUP BY q.q1;

但这无论如何都会创建一个临时表。

【讨论】:

  • 可能也可以使用 CTE。不确定 mySQL 是否支持这些。
  • 2006 年?耶!我想这表明 MySQL 非常关心跟上标准。
  • 他们没有做太多的改进他们的SQL语言支持,但是他们花了很多精力改进存储引擎的内部,使MySQL更稳定和更具可扩展性。那部分已经得到了回报。但是,是的,从开发人员的角度来看,MySQL 似乎有点停滞不前。
【解决方案2】:

SQL 查询实际上无法引用IN 子句中的值。我认为您必须将其分解为每个值的一个查询。比如:

SELECT 1 as q1, COUNT(1) FROM results WHERE q1 = '1'
UNION ALL
SELECT 2 as q1, COUNT(1) FROM results WHERE q1 = '2'
UNION ALL
SELECT 3 as q1, COUNT(1) FROM results WHERE q1 = '3'

Fiddle

注意:如果您的 IN 子句中有 很多 个值,那么您最好将代码编写为缺少 值假定为零。

【讨论】:

  • 资源密集程度如何...例如,如果我没有 20 而是说 400?
  • @Homer_J - 老实说我不知道​​。 MySQL 可能能够对其进行优化并进行一次表扫描或一次索引扫描,但您必须运行一些测试才能看到。
【解决方案3】:

一般来说,您无法查询不存在的内容。因此,您必须为其创建数据。使用联合来添加那些缺失的数据值。

select q1, COUNT(*) 
from results 
where q1 in ('1','2','3')
group by q1
union
select q1, 0
from (
  select '1' as q1
  union 
  select '2'
  union 
  select '3'
) as q
where q1 not in (
  select q1
  from results
)

【讨论】:

    猜你喜欢
    • 2012-10-04
    • 2020-01-13
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 2015-06-11
    • 1970-01-01
    相关资源
    最近更新 更多