2010-07-01 34 views
12

Tôi cần những điều sau đây, Bất kỳ ai cũng có thể giúp tôi làm điều đó.Nhiều Cấp bậc trong một bảng

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 

Tôi cần xếp hạng riêng biệt cho Cust_Type trên cùng và dưới cùng và tất cả điều này là trong MySQL.

+2

Bạn đang hỏi cách tạo bảng này? Làm cách nào để truy vấn bảng này? Cách truy vấn một bảng khác để nhận kết quả như thế này? – grossvogel

+0

Vui lòng sử dụng tính năng nhận xét theo câu trả lời bạn nhận được để làm rõ. Nếu một cái gì đó không phù hợp trong một bình luận, nó sẽ được chỉnh sửa vào câu hỏi của bạn (xem liên kết chỉnh sửa) –

Trả lời

20

Đây là một chút khó khăn. Bạn có thể muốn sử dụng các biến, chẳng hạn như trong ví dụ sau:

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; 

Phần (SELECT @curRow := 0, @curType := '') r cho phép khởi tạo biến mà không đòi hỏi một lệnh riêng SET.

trường hợp thử nghiệm:

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); 

Kết quả:

+------+-----------+-----------+---------+ 
| 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) 

Một trường hợp thử nghiệm:

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); 

Kết quả:

+------+-----------+-----------+---------+ 
| 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) 

Bạn rõ ràng có thể đặt hàng cust_type theo thứ tự tăng dần thay vì giảm dần. Tôi đã sử dụng giảm dần chỉ để có Top trước Bottom trong trường hợp thử nghiệm ban đầu.

+2

Giải pháp rất hay. Tôi hy vọng nhóm MySQL sẽ cung cấp các chức năng cửa sổ và phân tích để tránh những xung quanh công việc này. – Shiva

+0

Tôi không hiểu tại sao những điều trên không hoạt động khi tôi sử dụng \ @curRow: = 0 AND \ @curType: = cust_type thay vì: = 1 được sử dụng ở đây. – mathieu

+0

Tôi vừa thử sử dụng giải pháp này và nhận thấy có điều gì đó kỳ lạ. Tôi chỉ muốn xem giá trị hàng đầu cho mỗi nhóm, vì vậy tôi đã thêm 'có rank = 1' vào cuối truy vấn. Nó cho thấy các hàng chính xác, nhưng các cột xếp hạng là tất cả 2. Nếu tôi chỉ sử dụng truy vấn mà không có mệnh đề HAVING nó hoạt động chính xác (bắt đầu mỗi nhóm với rank = 1). Trong trường hợp nó quan trọng, thay vì sử dụng một bảng tôi đã sử dụng một cái nhìn, và các tiêu chí ORDER BY là trong định nghĩa khung nhìn. – Barmar

1

Điều không rõ ràng là cách xếp hạng mục (tôi giả định theo Doanh thu) hoặc bạn chỉ đang kéo một số giá trị nhất định (ví dụ: phần trên cùng và dưới cùng 3) vì vậy tôi cho rằng bạn muốn tất cả các giá trị . Dựa trên những giả định,

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' 

Nếu bạn đang cố gắng để làm điều này trong một truy vấn phi công đoàn duy nhất bạn có thể làm:

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 
3

Tôi tìm thấy một vấn đề với các giải pháp sử dụng CASE, @curRow, và @curType . Nó phụ thuộc vào kế hoạch thực thi mà MySQL sử dụng để xử lý truy vấn. Ví dụ, nó xuất hiện nếu bạn thêm một tham gia vào truy vấn. Sau đó, không có gì đảm bảo rằng thứ hạng sẽ được tính toán chính xác.

Làm một thay đổi nhỏ để câu trả lời:

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); 

Nếu tôi truy vấn chỉ bảng sales tôi nhận được thứ hạng theo thứ tự đúng, nhưng nếu tôi tham gia vào bảng cust_type các giá trị thứ hạng không còn đúng

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; 

Kết quả:

+------+-----------+-----------+---------+ 
| 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 là r unning truy vấn ban đầu vào bảng tạm thời và sau đó ORDER BY đang thi hành trên bảng tạm thời sau xếp hạng đã được tính toán.

2

này cũng tương tự như câu trả lời của Thomas, nhưng một chút đơn giản hơn:

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; 

Tôi không chắc chắn cách hiệu suất so với giải pháp của Daniel, đặc biệt là trên các tập dữ liệu rất lớn, hoặc nếu bạn phải sử dụng tham gia phức tạp.

0

Điều này phù hợp với tôi bằng cách giữ xếp hạng doanh thu bán hàng và đặt hàng riêng biệt.

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; 
Các vấn đề liên quan