2009-08-31 3 views
1

stackoverflow에 대한 SQL Top N 질문이 많이 있지만 상황과 일치하는 항목을 찾을 수없는 것 같습니다. 상위 n 개 쿼리에서 그룹화를 수행하고 싶습니다. 내 데이터는 이렇게 보입니다 (분명히 가짜 값으로).MySQL 상위 N 그룹화

MY_DATE IP_ADDRESS 
1/1/09  999.999.999.999 
1/1/09  999.999.999.999 
1/1/09  999.999.999.998 
... a lot more rows 

테이블의 날짜 범위는 몇 개월을 다루며 월간 수천 개의 행을 포함합니다. 내가하고 싶은 일은 하나의 쿼리에서 매월 10 개의 IP 주소가 가장 자주 발생했는지 알려주는 것입니다. 나는 다음을 사용하여 단일 한 달 동안이 작업을 수행 할 수 있습니다

SELECT DATE_FORMAT(MY_DATE, '%b-%y') AS "MONTH", IP_ADDRESS, COUNT(*) AS HITS 
FROM MY_DATA 
WHERE DATE_FORMAT(MY_DATE, '%b-%y') = 'JAN-09' 
GROUP BY DATE_FORMAT(MY_DATE, '%b-%y'), IP_ADDRESS 
ORDER BY HITS DESC 
LIMIT 10 

는하지만 내가 정말 원하는 것은 데이터 세트의 모든 달 동안 상위 N을 볼 수있을 것입니다. 그것은 본질적으로 내가 지정한 where 절을 사용하는 것을 금지합니다. 물론, 그렇게하면 모든 달 동안 10 점까지 얻습니다. 내가 찾고있는 결과는 다음과 같아야합니다.

MONTH IP_ADDRESS  COUNT(*) 
JAN-09 999.999.999.999 200 
JAN-09 999.999.999.998 150 
... (8 more rows of January) 
FEB-09 999.999.999.999 320 
FEB-09 999.999.999.998 234 
... (8 more rows of February) 
MAR-09 999.999.999.999 440 
... ETC. 

이 작업을 MySQL로 수행 할 수 있습니까? 내가 부딪히는 장벽은 MySQL이 UNION에 포함 된 쿼리 문 안에서 ORDER BY를 허용하지 않는다는 것입니다. 도와 주셔서 감사합니다!

답변

3

난 그냥 @Charles Bretana으로 한 given 매우 유사한 쿼리를 시도하려고하며 작업을 수행합니다. 나는 물건을 명확히하는 데 VIEW를 사용했다. 이제 세 가지를 보여

CREATE VIEW my_data_per_month as 
SELECT EXTRACT(YEAR_MONTH FROM my_date) AS month, 
    ip_address, COUNT(*) AS hits 
FROM my_data 
GROUP BY month, ip_address; 

SELECT * FROM my_data_per_month 
ORDER BY month ASC, hits DESC; 

+--------+-----------------+------+ 
| month | ip_address  | hits | 
+--------+-----------------+------+ 
| 200901 | 999.999.999.999 | 8 | 
| 200901 | 999.999.999.998 | 6 | 
| 200901 | 999.999.999.997 | 5 | 
| 200901 | 999.999.999.996 | 4 | 
| 200901 | 999.999.999.995 | 3 | 
| 200901 | 999.999.999.994 | 2 | 
| 200902 | 999.999.999.998 | 8 | 
| 200902 | 999.999.999.997 | 6 | 
| 200902 | 999.999.999.996 | 5 | 
| 200902 | 999.999.999.995 | 4 | 
| 200902 | 999.999.999.994 | 3 | 
| 200902 | 999.999.999.993 | 2 | 
| 200903 | 999.999.999.997 | 8 | 
| 200903 | 999.999.999.996 | 6 | 
| 200903 | 999.999.999.995 | 5 | 
| 200903 | 999.999.999.994 | 4 | 
| 200903 | 999.999.999.993 | 3 | 
| 200903 | 999.999.999.992 | 2 | 
+--------+-----------------+------+ 

:

CREATE TABLE my_data (
my_date DATE, 
ip_address CHAR(15) 
); 

달과 IP 주소 당 모든 계산에 대한 뷰를 만들기 ... 날짜/여기서 IPaddress 쌍 (도시하지 않음)의 무리를 삽입 한달에 IP 주소 :

SELECT m1.month, m1.ip_address, m1.hits 
FROM my_data_per_month m1 
LEFT OUTER JOIN my_data_per_month m2 
    ON (m1.month = m2.month AND m1.hits < m2.hits) 
GROUP BY m1.month, m1.ip_address 
HAVING COUNT(*) < 3 
ORDER BY m1.month ASC, m1.hits DESC; 

+--------+-----------------+------+ 
| month | ip_address  | hits | 
+--------+-----------------+------+ 
| 200901 | 999.999.999.999 | 8 | 
| 200901 | 999.999.999.998 | 6 | 
| 200901 | 999.999.999.997 | 5 | 
| 200902 | 999.999.999.998 | 8 | 
| 200902 | 999.999.999.997 | 6 | 
| 200902 | 999.999.999.996 | 5 | 
| 200903 | 999.999.999.997 | 8 | 
| 200903 | 999.999.999.996 | 6 | 
| 200903 | 999.999.999.995 | 5 | 
+--------+-----------------+------+ 
+0

나중에이 달로 돌아와서 마침내 이것을 시도해 보았습니다. 고맙습니다! –

0

이 첫 번째 거친 추측이지만,이

Select Month, Address 
From (Select DATE_FORMAT(MY_DATE, '%b-%y') Month, 
     IP_Address Address, Count(*) AddressCount 
     From MY_DATA 
     Group By DATE_FORMAT(MY_DATE, '%b-%y'), IP_Adress) Z 
    Join(Select DATE_FORMAT(MY_DATE, '%b-%y') Month, 
      IP_Address Address, Count(*) AddressCount 
     From MY_DATA 
     Group By DATE_FORMAT(MY_DATE, '%b-%y'), IP_Adress) ZZ 
    On ZZ.Month = Z.Month 
     And ZZ.AddressCount >= Z.AddressCount 
Group By Z.Month, Z.Address 
Where Count(ZZ.AddressCount) >= 10 
+0

죄송하지만, 유효한 SQL조차도 아닙니다. 제한을 어디에서하고 있습니까? –

+0

... 및 "ON"절 또는 연관된 where 절이 없어서 카티 전 곱이 생성됩니다. –

+0

@Charles :'JOIN'을'LEFT OUTER JOIN'으로 변경하십시오. 외부 쿼리의 'WHERE'가 'HAVING'으로 변경됩니다. 마지막 조건에서'> ='를'<='로 변경하십시오. –

관련 문제