2011-01-13 5 views
1

다음과 같은 데이터베이스가 있습니다.MySQL로 복잡한 SQL 쿼리?

[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 

기타

UNION을 사용하지 않고 이것을 달성하십시오. 나는 잠시 동안 복잡한 SQL을 수행하지 않았으며 내 머리를 아프게하고있다.

MySQL을 사용하고 있습니다.

카테고리, 제품 및 주문이 있고 각 카테고리의 주문 수를 기준으로 상위 10 개 제품을 원한 경우에도 이와 비슷한 방법이 될 수 있습니다.

+1

사람들이 MySQL 쿼리를 만드는 데 도움을주기를 원할 경우 테이블 정의를 포함해야합니다. – Dancrumb

+0

끝에 범주, 제품 및 주문 예제를 사용하면 표준 테이블 정의를 상상할 수 있습니다. 이 작업을 수행하는 방법에 대한 개념적인 질문 일뿐입니다. 나는 쿼리를 작성하게되어서 기쁘다. 나는 유니온을 사용하지 않고 어떻게 구조화 하는지를 모른다. – oak

+0

비슷한 질문에 당신을 안내하기 위해 '가장 훌륭한 그룹당'이라고 태그가 붙어 있습니다 - 나는 다른 사람이 이것을 한 것을 보았습니다 (그리고 정확한 코멘트를했습니다 :-). 어쨌든,이 작업은 SQL Server에서'ROW_NUMBER (... PARTITION ON ...) '로 끝납니다. 따라서 종료 된 경우에는 MySQL과 동등한 항목을 찾아야합니다. –

답변

1

이 쿼리는 작동합니다.

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; 

아무튼 : 쿼리가이 데이터를 beentested있다

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

:

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 

나는이 테이블 명시된 관계가 존재 가정, 따라하기 쉬워야 필드 이름을 사용 각각의 "상위 10 개"에 대한 충분한 레코드를 만들지 만 COUNTER 열의 순위가 올바르게 표시됩니다. 처음에만 상위 2 또는 3 당 상태를 보여주고, 다음 2 ~ 3처럼 뭔가를 줄이고, 카운터 열을 확인하기 위해이

where counter <= 10 

에서이 필터를 남겨, 그것은이 작은 데이터 집합에 대해 작업을 참조하십시오.

+0

관련 항목 : http://explainextended.com/2009/03/05/row-sampling/ –