没有结果时添加行值 - MySQL

Adding Row Values when there are no results - MySQL

问题陈述:我需要我的结果集包含自然不会return的记录,因为它们是 NULL。

由于我的代码似乎太长了,我将在此处放一些简化的代码。

Table ScoresCompany_typeCompanyScoreProject_ID

Select Score, Count(Project_ID)
    FROM Scores
    WHERE company_type= :company_type
    GROUP BY Score

结果如下:

Score   Projects
5       95
4       94
3       215
2       51
1       155

一切正常,直到我对 company_type 应用了一个不包含 5 个分数类别之一的结果的条件。发生这种情况时,我的结果集中不再有 5 行。

显示如下:

Score   Projects
5       5
3       6
1       3

我希望它像这样显示:

Score   Projects
5       5
4       0
3       6
2       0
1       3

我需要结果始终显示 5 行。 (分数 = 1-5)


我尝试了 Spencer7593 提供的以下方法之一。我的简化查询现在看起来像这样:

SELECT i.score AS Score, IFNULL(count(*), 0) AS Projects FROM (SELECT 5 AS 分数 联合所有 SELECT 4 联合所有 SELECT 3 联合所有 SELECT 2 联合所有 SELECT 1) 我 LEFT JOIN 得分 Scores.score = i.score 按分数分组 按 i.score 排序

并给出了以下结果,除了项目中带有 1 的行实际上应该是 0 之外,这是准确的,因为它们是由 "i" 派生的。没有得分为 5 或 2 的项目。

Score   Projects
5       1
4       5
3       6
2       1
1       3

已解决!我只需要调整我的计数以专门查看项目计数 - count(project) 而不是 count(*)。这 return 达到了预期的结果。

如果您总是希望查询 return 5 行,Score 值为 5,4,3,2,1... 您将需要一个行源来提供这些 Score 值。

一种方法是对 return 这些固定值使用简单查询,例如

 SELECT 5 AS score
 UNION ALL SELECT 4
 UNION ALL SELECT 3
 UNION ALL SELECT 2
 UNION ALL SELECT 1

然后将该查询用作内联视图,并对当前查询的结果执行外连接操作

 SELECT i.score                AS `Score`
      , IFNULL(q.projects,0)   AS `Projects`
   FROM ( SELECT 5 AS score
          UNION ALL SELECT 4
          UNION ALL SELECT 3
          UNION ALL SELECT 2
          UNION ALL SELECT 1
        ) i
   LEFT
   JOIN (
          -- the current query with "missing" Score rows goes here
          -- for completeness of this example, without the query 
          -- we emulate that result with a different query
          SELECT 5 AS score, 95 AS projects
          UNION ALL SELECT 3, 215
          UNION ALL SELECT 1, 155
        ) q
     ON q.score = i.score
  ORDER BY i.score DESC

在这个例子中不一定是视图查询。但是确实需要一个行源,可以从中 return 编辑行。例如,您可以有一个简单的 table,其中包含这五行,以及这五个分数值。

这只是一般方法的示例方法。可以将您现有的查询修改为 return 您想要的行。但是如果没有看到查询、模式和示例数据,我们无法判断。


跟进

基于对问题的编辑,显示当前查询的示例。

如果我们保证Score的五个值总是出现在Scorestable中,我们可以做条件聚合,这样写一个查询:

 SELECT s.score
      , COUNT(IF(s.company_type = :company_type,s.project_id,NULL)) AS projects
  FROM Scores s
 GROUP BY s.score
 ORDER BY s.score DESC

请注意,这将需要扫描所有行,因此它的性能可能不佳。 "trick" 是 IF 函数,当该行已被 WHERE 子句排除时,它 return 是一个 NULL 值代替 project_id。)

如果我们保证 project_id 是非 NULL,我们可以使用更简洁的 MySQL shorthand 表达式来获得等效的结果...

      , IFNULL(SUM(s.company_type = :company_type),0) AS projects

这是有效的,因为当比较为 TRUE 时 MySQL returns 1,否则 returns 0 或 NULL。

尝试这样的事情:

select distinct score
from (
    select distinct score from scores
) s
left outer join (
    Select Score, Count(Project_ID) cnt
    FROM Scores 
    WHERE company_type= :company_type
) x
on s.score = x.score

如果没有 group by 语句,您发布的查询将无法工作。但是,即使在那里,如果您没有针对该公司类型的那些特定分数,它也不会起作用。

一种选择是使用 outer join。不过,这需要做更多的工作。

这是另一个使用 conditional aggregation 的选项:

select Score, sum(company_type=:company_type) 
from Scores
group by Score