使用编号结果集(带有间隙)更改查询以返回没有间隙的结果,包含每个数字。

时间:2012-06-21 15:34:20

标签: mysql sql

我有一个select语句:select a, b, [...];,它返回结果:

a|b
---------
1|8688798
2|355744
4|457437
7|27834

我希望它返回:

a|b
---------
1|8688798
2|355744
3|0
4|457437
5|0
6|0
7|27834

示例查询不能执行我想要的操作,因为它没有间隙编号:

select
    sub.num_of_ratings,
    count(sub.rater)
from
(
    select 
        r.rater_id as rater,
        count(r.id) as num_of_ratings
    from ratings r
    group by rater
) as sub
group by num_of_ratings;

查询说明: 如果用户对另一个用户进行评级,则评级将列在表评级中,评级用户的ID将保留在rater_id字段中。实际上,我会检查所有在评级中引用的用户,并计算我为该用户找到的评分记录数rater / num_of_ratings,然后我使用此结果查找有多少用户评分了给定次数

最后我知道有多少用户评价一次,有多少用户评价两次等等。我的问题是计数(sub.rater)的数字从1,2,3,4,5开始正常...但是,对于更大的数字,存在差距。这是因为可能有一个用户评分1028次 - 但没有用户评分1027次。

我不想应用存储过程循环结果或类似的东西。是否可以在不使用存储过程,循环或创建临时表的情况下填充结果中的空白?

3 个答案:

答案 0 :(得分:3)

如果您有一系列数字,那么您可以与该表进行联接并正确填补空白。

您可以查看有关如何获取序列的以下问题: generate an integer sequence in MySQL

以下是发布的答案之一,可能很容易使用生成1到10,000之间数字的限制:

SELECT @row := @row + 1 as row FROM 
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, 
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3, 
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4, 
(SELECT @row:=0) t5

答案 1 :(得分:0)

使用一系列数字,您可以加入结果集。例如,假设您的号码列表位于名为numbersList的表中,列号为:

Select number, Count 
from
  numbersList left outer join
  (select
      sub.num_of_ratings,
      count(sub.rater) as Count
  from
  (
      select 
          r.rater_id as rater,
          count(r.id) as num_of_ratings
      from ratings r
      group by rater
  ) as sub
  group by num_of_ratings) as num

on num.num_of_ratings=numbersList.number
where numbersList.number<max(num.num_of_ratings) 

显然,您的号码列表必须大于您的最大值,并且限制将允许它不会使所有号码都达到最大值。 (如果MySQL不允许使用where类型的where子句,则可以将where子句保留为列出所有数字,或者以各种方式修改查询以获得相同的结果。)

答案 2 :(得分:0)

@mazzucci:查询太神奇了,你实际上并没有解释查询。

@David:我无法为此目的创建表格(如问题中所述)

基本上我需要的是一个返回无间隙数字列表的选择。然后我可以在该结果集上保持连接并将NULL视为0。

我需要的是一个任意表,它保存的记录多于最终列表的长度。我在下面的示例中使用表用户:

select @row := @row + 1 as index
    from (select @row := -1) r, users u
limit 101;

此查询返回一组数字von 0到100.使用它作为左连接中的子查询最终填补了空白。

用户只是一个假人,可以保持关系引擎的运行,从而逐步产生数字。

select t1.index as a, ifnull(t2.b, 0) as b
from (
    select @row := @row + 1 as index
        from (select @row := 0) r, users u
    limit 7
) as t1
left join (
    select a, b [...]
) as t2
on t1.index = t2.a;

我没有亲自尝试这个查询,所以如果有一点缺陷,请跟我一起使用merci。但从技术上讲它是有效的。你明白我的观点。

修改

刚刚使用这个概念来获得一个无间隙的日期列表,以便将连接度量保留在其上:

select @date := date_add(@date, interval 1 day) as date
    from (select @date := '2010-10-14') d, users u
limit 700

从2010/10/15开始,再迭代699天。