2009-06-25 5 views
4

나는 종류, 제품 및 조사를 가진 테이블이있다. 모든 정수. 각 카테고리에 대해 상위 10 개 제품 (최고 수)을 제공하는 가장 효율적인 쿼리를 찾고 있습니다.Mysql 한도로 가입 하시겠습니까?

여러 개의 subselect와 조인을 시도했지만 단일 쿼리에서이를 수행하는 방법을 알 수 없습니다. 당신의 도움을 주셔서 감사합니다.

답변

7
select a.* from t a where 10 > (
    select count(*) from t b 
    where b.category=a.category 
    and b.count<a.count 
) 

나는 이것이 당신이 필요하다고 생각합니다.

2

This article 내 문제를 해결한다고 생각합니다.

기본적으로, 테이블이 작은 경우,이 같은 가입 자체 불평등을 할 수 있다고 말한다 :

SELECT t1.*, COUNT(*) AS countRank 
FROM tbl AS t1 
JOIN tbl AS t2 ON t1.category=t2.category AND t1.count <= t2.count 
GROUP BY t1.category, t1.count 
HAVING countRank <= 10 
ORDER BY category,count DESC; 

그것은 비용이 많이 드는 작업이지만, 작은 테이블을 위해 당신은 괜찮을 것이다. 대형 테이블을 사용하는 경우 하나의 쿼리로이를 수행하는 것을 잊어 버리고 솔루션에 대한 다른 접근 방식을 구현해야합니다.

0
select a.* from `table` a where a.product in (
    select b.product from `table` b 
    where b.category=a.category 
    order by b.count desc 
    limit 10 
) 

나는 이것이 좋은 방법이라고 생각하지만, MySQL의 반환 :

MySQL 返回:文档 
#1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' 
4

A는 약간 내 블로그에이 문서에서 쿼리를 수정 :이 효율적으로 작동하려면

 

SELECT l.* 
FROM (
     SELECT category, 
       COALESCE(
       (
       SELECT count 
       FROM mytable li 
       WHERE li.category = dlo.category 
       ORDER BY 
         li.category DESC, li.count DESC, li.id DESC 
       LIMIT 9, 1 
       ), CAST(-1 AS DECIMAL)) AS mcount 
       COALESCE(
       (
       SELECT id 
       FROM mytable li 
       WHERE li.category = dlo.category 
       ORDER BY 
         li.category DESC, li.count DESC, li.id DESC 
       LIMIT 9, 1 
       ), CAST(-1 AS DECIMAL)) AS mid 
     FROM (
       SELECT DISTINCT category 
       FROM mytable dl 
       ) dlo 
     ) lo, mytable l 
WHERE l.category >= lo.category 
     AND l.category <= lo.category 
     AND (l.count, l.id) >= (lo.mcout, lo.id) 

당신은 (category, count, id)에 복합 인덱스를 작성해야 .

참고 l.category >= lo.category AND l.category <= lo.category 대신 단지의의 사용은 : l.category = lo.category

이 해킹을하는 것입니다 MySQL 사용 효율 Range check for each record

1
SET @row = 0; 
SET @category = 0; 
  
SELECT top.* 
FROM (
  SELECT IF(@category = p.cId, @row := @row + 1, @row := 1) rowNumber, 
    (@category := p.cId) categoryId, 
    p.pId 
  FROM (
    SELECT c.cId, 
      c.pId 
    FROM prod pr 
      INNER JOIN cat_prod c ON c.pId = pr.id 
    GROUP BY c.cId, c.pId 
    ) p 
  ) top 
HAVING top.rowNumber < 4;