在不使用子查询的情况下限制结果

时间:2012-08-09 01:55:46

标签: mysql sql database

我有两张桌子:

  • business(id,name)
  • 类别(id,name,business_id)

如何输出数据库中的所有类别,每个类别中有5个业务?

例如,如果db中有3个类别,那么我想:

category 1
--------------
business 1
business 2
business 3
business 4
business 5

category 2
---------------
business 6
business 7
business 8
business 9
business 10

category 3
------------------
business 11
business 12
business 13
business 14
business 15

我知道如何做的唯一方法是从db中获取所有类别,然后以编程方式遍历每个类别并触发另一个查询以获取每个类别中的所有业务。

还有其他方式吗?

3 个答案:

答案 0 :(得分:2)

您可以使用排名方法,但这涉及子查询。

 select id,business_name,cat_name,cat_id from
(SELECT *,@i := CASE WHEN ( @temp_bid <> m.id ) THEN 1                      
            ELSE     @i+1      
            END AS rank ,
            @temp_bid:=m.id as dlset 
 FROM 
 ( Select a.id as id,a.name as business_name,b.name as cat_name,b.id as cat_id
   from business a left outer join categories b on a.id=b.business_id ) m)k,
 (SELECT @i:=0)i,(SELECT @i2:=0)i2
where rank<=5
 ORDER BY business_name,rank desc;

SQL FIDDLE HERE.

答案 1 :(得分:1)

您可以使用WHERE子句中的相关子查询执行此操作:

select b.name, c.id
from categories c join
     business b
     on c.business_id = b.id
where c.id in (select c2.id
               from categories c2
               where c2.business_id = c.business_id
               order by rand()
               limit 5
              )

在支持排名功能的其他数据库中,这更简单。

如果此子查询不支持限制,则必须使用自联接执行此操作。哎呀,哎呀,哎呀:

with bc as (
     select b.name, c.id
     from categories c join
          business b
          on c.business_id = b.id
   )
select bc.name, bc.id
from bc join
     bc bcprev
     on bc.name = bcprev.name and
        bcprev.id <= bc.id
group by bc.name, bc.id
having count(*) <= 5

这不会得到5个随机类别。相反,它获得了具有最低ID的五个。

罗伯史密斯编辑:

以上查询在MySQL 5.5.25中返回错误,但以下工作:

select bc.name, bc.id
from
  (
     select b.name, c.id
     from categories c join
          business b
          on c.business_id = b.id
   ) bc join
   (
     select b.name, c.id
     from categories c join
          business b
          on c.business_id = b.id
   ) bcprev
     on bc.name = bcprev.name and
        bcprev.id <= bc.id
group by bc.name, bc.id
having count(*) <= 5

并且似乎返回了这个预期的结果。

请参阅http://sqlfiddle.com/#!2/ea78a/9

答案 2 :(得分:0)

如果将类别 - 业务关系存储在单独的表中,会不会更好?如果是,那么您可以使用此查询:

SELECT
    c_name,
    b_name
FROM
(
    SELECT
        c.name AS c_name,
        b.name AS b_name,
        (@row := IF(@last = cat_id, @row + 1, 1)) AS row,
        @last := cat_id
    FROM
        (SELECT @row := 0, @last = '') a,
        cat_bus cb
    INNER JOIN
        cat c ON c.id = cb.cat_id
    INNER JOIN
        bus b ON b.id = cb.bus_id
    ORDER BY
        c.name,
        b.name
) d 
WHERE
    d.row <= 5
ORDER BY
    c_name,
    b_name  

请参阅sqlfiddle.com了解结果。