简体   繁体   English

使用MySQL进行复杂的SQL查询?

[英]Complex SQL Query with MySQL?

I have a database with: 我有一个数据库:

[business] must have a [location]
[location] may have many [business]
[location] may have many [postcode]
[postcode] may be for many [location]
[postcode] must have a [state]

I want a query to return the top 10 locations for each state in terms of the business count. 我希望查询返回每个州的业务计数最高的10个位置。

To make more sense, it may come out: 为了更有意义,它可能会出来:

Western Australia
  - perth
  - bunbury
  - etc. up to 10

(ie perth has the most businesses listed in Western Australia) (即,珀斯在西澳大利亚州列出的企业最多)

Victoria
  - melbourne
  - st kilda
  - etc. up to 10

Etc. 等等。

I was hoping to achieve this without using UNION. 我希望在不使用UNION的情况下实现这一目标。 I haven't done complex SQL for a while and it's hurting my head. 我有一段时间没有做复杂的SQL了,这伤了我的头。

I am using MySQL. 我正在使用MySQL。

A similar way to put this would be if you had categories, products and orders and wanted the the top ten products in terms of order count for each category. 如果您具有类别,产品和订单,并且希望按每个类别的订单数来排名前十位的产品,则可以采用类似的方法。

This query should work. 此查询应该工作。

select * from (
    select a.state, a.location_id, C,
        @n:=case when @s=a.state then @n+1 else 1 end counter,
        @s:=a.state
    from (select @s:=null) b, (
        select pc.state, b.location_id, COUNT(b.location_id) C
        from postcode pc
        inner join location_postcode lp on lp.postcode_id=pc.id
        inner join business b on b.location_id=lp.location_id
        group by pc.state, b.location_id
        order by pc.state, C desc
    ) a
) c
where counter <= 10

I used field names that should be easy to follow, assuming these tables exist with stated relationships: 我使用了易于理解的字段名称,假设这些表以规定的关系存在:

business M-1 location
location M-M postcode
    (expands to) => location 1-M location_postcode M-1 postcode
postcode M-1 state

The query has beentested with this data: 查询已使用以下数据进行了测试:

create table business (location_id int);
insert into business select floor(rand()*10);
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
insert into business select floor(rand()*10) from business;
create table location_postcode (location_id int, postcode_id int);
insert into location_postcode select 1,1;
insert into location_postcode select 2,1;
insert into location_postcode select 3,1;
insert into location_postcode select 4,2;
insert into location_postcode select 5,1;
insert into location_postcode select 5,2;
insert into location_postcode select 6,1;
insert into location_postcode select 6,3;
insert into location_postcode select 7,1;
insert into location_postcode select 7,4;
insert into location_postcode select 8,5;
insert into location_postcode select 9,6;
insert into location_postcode select 10,7;
create table postcode (id int, state int);
insert into postcode select 1,1;
insert into postcode select 2,2;
insert into postcode select 3,3;
insert into postcode select 4,4;
insert into postcode select 5,4;
insert into postcode select 6,5;
insert into postcode select 7,5;

Which doesn't quite create enough records for a "top 10" from each, but you will see how the COUNTER column is ranking correctly. 这并不能为每个“前10名”创建足够的记录,但是您将看到COUNTER列的排名正确。 To see it working against this small data set, first leave this filter in there 要查看它是否适用于此较小的数据集,请首先将该过滤器留在此处

where counter <= 10

to check the COUNTER column, then reduce it to something like 2 or 3, to show only the top 2 or 3 per state. 检查COUNTER列,然后将其减少为2或3,仅显示每个州的前2或3位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM