[SQL] 하나 개의 테이블에 여러 계급
SQL하나 개의 테이블에 여러 계급
나는 다음 필요 캔 사람이 나를 그렇게 도와주세요.
Rank Cust_Type Cust_Name Revenue
1 Top A 10000
2 Top B 9000
3 Top C 8000
1 Bottom X 5000
2 Bottom Y 6000
3 Bottom Z 7000
나는 상부 및 하부 Cust_Type에 대해 별도의 대열에 필요한 모든이의 MySQL입니다.
해결법
-
==============================
1.이것은 조금 까다 롭습니다. 당신은 다음 예제와 같이 변수를 사용할 수 있습니다 :
이것은 조금 까다 롭습니다. 당신은 다음 예제와 같이 변수를 사용할 수 있습니다 :
SELECT ( CASE cust_type WHEN @curType THEN @curRow := @curRow + 1 ELSE @curRow := 1 AND @curType := cust_type END ) + 1 AS rank, cust_type, cust_name, revenue FROM sales, (SELECT @curRow := 0, @curType := '') r ORDER BY cust_type DESC, revenue DESC;
제 (SELECT @curRow = 0 @curType = ') R 부는 별도 SET 명령을 필요로하지 않고, 변수를 초기화 할 수있다.
테스트 케이스 :
CREATE TABLE sales (cust_type varchar(10), cust_name varchar(10), revenue int); INSERT INTO sales VALUES ('Top', 'A', 10000); INSERT INTO sales VALUES ('Top', 'B', 9000); INSERT INTO sales VALUES ('Top', 'C', 8000); INSERT INTO sales VALUES ('Bottom', 'X', 5000); INSERT INTO sales VALUES ('Bottom', 'Y', 6000); INSERT INTO sales VALUES ('Bottom', 'Z', 7000);
결과:
+------+-----------+-----------+---------+ | rank | cust_type | cust_name | revenue | +------+-----------+-----------+---------+ | 1 | Top | A | 10000 | | 2 | Top | B | 9000 | | 3 | Top | C | 8000 | | 1 | Bottom | Z | 7000 | | 2 | Bottom | Y | 6000 | | 3 | Bottom | X | 5000 | +------+-----------+-----------+---------+ 6 rows in set (0.00 sec)
또 다른 테스트 케이스 :
CREATE TABLE sales (cust_type varchar(10), cust_name varchar(10), revenue int); INSERT INTO sales VALUES ('Type X', 'A', 7000); INSERT INTO sales VALUES ('Type X', 'B', 8000); INSERT INTO sales VALUES ('Type Y', 'C', 5000); INSERT INTO sales VALUES ('Type Y', 'D', 6000); INSERT INTO sales VALUES ('Type Y', 'E', 4000); INSERT INTO sales VALUES ('Type Z', 'F', 4000); INSERT INTO sales VALUES ('Type Z', 'G', 3000);
결과:
+------+-----------+-----------+---------+ | rank | cust_type | cust_name | revenue | +------+-----------+-----------+---------+ | 1 | Type Z | F | 4000 | | 2 | Type Z | G | 3000 | | 1 | Type Y | D | 6000 | | 2 | Type Y | C | 5000 | | 3 | Type Y | E | 4000 | | 1 | Type X | B | 8000 | | 2 | Type X | A | 7000 | +------+-----------+-----------+---------+ 7 rows in set (0.00 sec)
당신은 분명히 내림차순 대신 오름차순에서 cust_type을 주문할 수 있습니다. 난 그냥 원래 테스트 케이스의 바닥 전에 탑을 가지고 내림차순으로 사용됩니다.
-
==============================
2.나는 CASE, @curRow 및 @curType를 사용하여 솔루션에 문제가 있음을 발견했다. 그것은 MySQL이 쿼리를 처리하는 데 사용하는 실행 계획에 따라 달라집니다. 예를 들어, 당신이 쿼리에 조인 추가하는 경우 표시됩니다. 그런 다음 순위를 올바르게 계산하는 것입니다 않는다는 보장은 없습니다.
나는 CASE, @curRow 및 @curType를 사용하여 솔루션에 문제가 있음을 발견했다. 그것은 MySQL이 쿼리를 처리하는 데 사용하는 실행 계획에 따라 달라집니다. 예를 들어, 당신이 쿼리에 조인 추가하는 경우 표시됩니다. 그런 다음 순위를 올바르게 계산하는 것입니다 않는다는 보장은 없습니다.
대답에 약간의 변화를 만들기 :
CREATE TABLE sales (cust_type_id int, cust_name varchar(10), revenue int); CREATE TABLE cust_type (cust_type_id int, type_name varchar(10)); INSERT INTO cust_type VALUES (1, 'Bottom'); INSERT INTO cust_type VALUES (2, 'Top'); INSERT INTO sales VALUES (2, 'A', 10000); INSERT INTO sales VALUES (2, 'B', 9000); INSERT INTO sales VALUES (2, 'C', 8000); INSERT INTO sales VALUES (1, 'X', 5000); INSERT INTO sales VALUES (1, 'Y', 6000); INSERT INTO sales VALUES (1, 'Z', 7000);
난 단지 판매 테이블을 쿼리하면 나는 올바른 순서로 순위를 얻을,하지만 난 cust_type 테이블에 가입하면 순위 값은 더 이상 정확
SELECT ( CASE s.cust_type_id WHEN @curType THEN @curRow := @curRow + 1 ELSE @curRow := 1 AND @curType := s.cust_type_id END ) AS rank, t.type_name, s.cust_name, s.revenue FROM sales s, cust_type t, (SELECT @curRow := 0, @curType := 0) r WHERE s.cust_type_id = t.cust_type_id ORDER BY t.type_name DESC, s.revenue DESC;
결과:
+------+-----------+-----------+---------+ | rank | type_name | cust_name | revenue | +------+-----------+-----------+---------+ | 1 | Top | A | 10000 | | 2 | Top | B | 9000 | | 3 | Top | C | 8000 | | 3 | Bottom | Z | 7000 | | 2 | Bottom | Y | 6000 | | 1 | Bottom | X | 5000 | +------+-----------+-----------+---------+
MySQL은 임시 테이블에 초기 쿼리를 실행하고, 순위가 이미 계산 된 후 다음 ORDER BY는 임시 테이블에 대해 실행됩니다.
-
==============================
3.이것은 토마스의 대답과 비슷하지만 조금 더 간단 :
이것은 토마스의 대답과 비슷하지만 조금 더 간단 :
SELECT (SELECT COUNT(Cust_Type) FROM sales WHERE Cust_Type = S.Cust_Type AND Revenue >= S.Revenue) AS Rank, Cust_Type, Cust_Name, Revenue FROM sales AS S ORDER BY Cust_Type DESC, Rank;
나는 성능이 특히 매우 큰 데이터 세트에, 다니엘의 솔루션과 비교하지 않도록 어떻게 해요, 또는 사용할 경우 복잡한 조인.
-
==============================
4.무엇 정확하게 명확하지 것은 (나는 수익으로 가정) 또는 당신이 모든 값을 원하는 가정 있도록 여부에만 값의 특정 숫자 (예를 들어, 상위 3 개 및 하단 3) 당기는 항목이 평가되는 방법입니다. 그 가정을 감안할 때,
무엇 정확하게 명확하지 것은 (나는 수익으로 가정) 또는 당신이 모든 값을 원하는 가정 있도록 여부에만 값의 특정 숫자 (예를 들어, 상위 3 개 및 하단 3) 당기는 항목이 평가되는 방법입니다. 그 가정을 감안할 때,
Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue > T.Revenue ) + 1 As Rank From Table As T Where Cust_Type = 'Top' Union All Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue < T.Revenue ) + 1 As Rank From Table As T Where Cust_Type = 'Bottom'
당신은 당신이 할 수있는 쿼리 하나의 비 노조에서이 작업을 수행하려고 한 경우 :
Select Cust_Name, Cust_Type , Case Z.Cust_Type When 'Top' Then Z.TopRank Else Z.BottomRank End As Rank From ( Select Cust_Name, Cust_Type , (Select Count(*) From Table As T1 Where T1.Revenue > T.Revenue ) + 1 As TopRank , (Select Count(*) From Table As T1 Where T1.Revenue < T.Revenue ) + 1 As BottomRank From Table As T ) As Z
-
==============================
5.판매 수익의 순위 및 별도의 주문을 유지함으로써 나를 위해이 작동합니다.
판매 수익의 순위 및 별도의 주문을 유지함으로써 나를 위해이 작동합니다.
SELECT (Select count(s1.revenue)+1 from sales s1 where s.cust_type_id = s1.cust_type_id and s1.revenue > s.revenue) As rank, t.type_name, s.cust_name, s.revenue FROM sales s LEFT JOIN cust_type t USING(cust_type_id) Group by t.type_name,s.cust_name,s.revenue DESC order by s.revenue DESC;
-
==============================
6.테이블 문제를 가입하기 위해, 나는 해결책을 찾아 냈다.
테이블 문제를 가입하기 위해, 나는 해결책을 찾아 냈다.
내가 임시 테이블을 만들고, 나는 순위에 원하는 값의 순서를 유지 MySQL을 이런 식으로.
DROP TEMPORARY TABLE IF EXISTS tmp_mytable; CREATE TEMPORARY TABLE tmp_mytable ENGINE = MEMORY SELECT mytable.id AS id, mytable.login AS Login, cliente.myrank_id AS id_myrank, mytable.rankvalue AS rankvalue FROM mytable INNER JOIN myjoin ON (mytable.id_myjoin = myjoin.id) ORDER BY 3, 4 DESC; SELECT id, login, IFNULL(id_myrank, 0) AS id_myrank, rankvalue, @rank := IF(@prev_born = IFNULL(id_myrank, 0), @rank + 1, 1) AS ranking, @prev_Born := IFNULL(id_myrank, 0) AS fake_field FROM tmp_mytable, (select @prev_born := 0, @rank := 0) r -- HAVING ranking < 20;
* PS : 내가보기 창조했지만, 너무 작동하지 않습니다.
from https://stackoverflow.com/questions/3162389/multiple-ranks-in-one-table by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] MySQL의 트리거 저장 트리거는 이미 저장 트리거를 호출 문에 의해 사용됩니다 (0) | 2020.04.21 |
---|---|
[SQL] MySQL은 GREATEST와 유사한 SQL Server 2008의 기능? (0) | 2020.04.21 |
[SQL] 변수 열 이름 동적 업데이트 문 (0) | 2020.04.21 |
[SQL] CROSS에 포스트 그레스 아날로그는 SQL 서버에 적용 (0) | 2020.04.21 |
[SQL] SQL 서버 UNION - 행동 BY 기본 ORDER 무엇 (0) | 2020.04.21 |