Сложный SQL-запрос с MySQL? - PullRequest
       14

Сложный SQL-запрос с MySQL?

1 голос
/ 13 января 2011

У меня есть база данных с:

[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]

Я хочу, чтобы запрос возвращал 10 лучших местоположений для каждого штата с точки зрения количества предприятий.

Чтобы иметь больше смысла, может получиться:

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

(т. Е. В Перте больше всего предприятий, перечисленных в Западной Австралии)

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

1012 * Etc. *

Я надеялся достичь этого без использования UNION. Некоторое время я не делал сложный SQL, и мне больно.

Я использую MySQL.

Аналогичным образом это можно сделать, если у вас есть категории, продукты и заказы, и вы хотите получить первую десятку продуктов по количеству заказов для каждой категории.

1 Ответ

1 голос
/ 13 января 2011

Этот запрос должен работать.

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

Я использовал имена полей, за которыми должно было легко следовать, предполагая, что эти таблицы существуют с установленными отношениями:

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

Запрос был протестирован с этими данными:

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;

Который не создает достаточно записей для «10 лучших» из каждого, но вы увидите, как правильно расположился столбец СЧЕТЧИК. Чтобы увидеть, как он работает с этим небольшим набором данных, сначала оставьте этот фильтр там

where counter <= 10

чтобы проверить столбец СЧЕТЧИК, затем уменьшите его до 2 или 3, чтобы отображались только верхние 2 или 3 для каждого состояния.

...