0

我有 2 张桌子:

  • 业务(ID,名称)
  • 类别(id、名称、business_id)

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

例如,如果数据库中有 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 中获取所有类别,然后以编程方式循环遍历每个类别并触发另一个查询以获取每个类别中的所有业务。

还有其他方法吗?

4

3 回答 3

2

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

 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 小提琴在这里。

于 2012-08-09T01:57:39.320 回答
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

于 2012-08-09T02:13:54.133 回答
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

于 2012-08-09T03:25:18.007 回答