2009-01-20 34 views
19

Nếu tôi có một bảng USER nhưSQL chọn thành viên thứ n của nhóm

class | age 
-------------- 
1  20  
3  56 
2  11 
1  12 
2  20 

Sau đó, tôi có thể dễ dàng có được người dùng trẻ nhất trong mỗi lớp qua

select class, min(age) 
from user 
group by class; 

Tương tự như vậy, bằng cách thay thế phút với max, Tôi có thể nhận được lâu đời nhất. Nhưng làm thế nào tôi có thể nhận được trẻ em thứ 10 (hoặc lâu đời nhất) trong mỗi lớp học? Nhân tiện, tôi đang sử dụng MySql v.5.0.

Chúc mừng,

Trả lời

0

Nó khá dễ dàng trong SQL Server:

select 
    * 
from(
    select 
     *, 
     row_number() over(order by age asc) as eldest 
    from class order by age asc) a 
where a.eldest = 10 

Tiếp theo khuôn mẫu đó, cho MySQL, tôi nghĩ rằng bạn sẽ muốn xem xét điều này: http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/

+0

Phương pháp trong liên kết CO làm việc nhưng nó là một chút một hack. Nó cũng rất nhanh. Đối với một số tiền phạt, cho sản xuất không! –

11
SELECT a.class, 
(
    SELECT b.age 
    FROM users b 
    WHERE b.class = a.class 
    ORDER BY age 
    LIMIT 1,1 
) as age 
FROM users a 
GROUP BY a.class 

Sẽ có đứa trẻ thứ 2 trong mỗi lớp. Nếu bạn muốn trẻ thứ 10, bạn sẽ làm LIMIT 9,1 và nếu bạn muốn có tuổi đời thứ 10, bạn sẽ làm ORDER BY age DESC.

+1

Điều đó sẽ mang lại cho tôi tổng thể lâu đời nhất thứ 10, chứ không phải là thứ 10 lâu đời nhất trong mỗi lớp. –

+0

Rất tiếc, không nhận thấy anh ấy muốn nhóm. Đang sửa ... –

+0

Điều đó dường như không hoạt động với MySQL v5.5: L ERI 1235 (42000): Phiên bản MySQL này chưa hỗ trợ 'LIMIT & IN/ALL/ANY/SOME subquery' – Marcus

0
SELECT 
    userid, 
    class, 
    age, 
    ( SELECT COUNT(1) FROM user 
      WHERE class = c.class AND age > u.age 
    ) AS oldercount 
FROM user AS u 
WHERE oldercount = 9 
GROUP BY class 

hoặc

SELECT userid, 
     class, 
     age 
    FROM user AS u  
    WHERE (SELECT COUNT(1) FROM class WHERE class = c.class AND age > u.age) = 9 
GROUP BY class 
+0

Cũng sẽ cần một khóa duy nhất nếu hai người có cùng độ tuổi và bạn chỉ muốn trả lại một trong số họ. –

+0

Truy vấn đầu tiên gây ra lỗi: "Cột không xác định" trẻ "trong" nơi khoản "" –

+0

Cả hai đều quét toàn bộ lớp cho mỗi bản ghi trong bảng nguồn. Nên có thể làm được mà không cần nhấn một luật hình vuông ... – MatBailie

1

Các chỉ sql cách độc lập (ngay cả khi bạn không có truy vấn con mysql < 5)

select u1.class, u1.age, count(*) from  user u1 join user u2 
on u1.class = u2.class and u1.age >= u2.age 
group by u1.class, u1.age 
having count(*) = [number] 

được bạn [số] lâu đời nhất mỗi lớp

select u1.class, u1.age, count(*) from  user u1 join user u2 
on u1.class = u2.class and u1.age <= u2.age 
group by u1.class, u1.age 
having count(*) = [number] 

cho bạn [số] trẻ nhất trên mỗi lớp

Nếu hai người có cùng độ tuổi thì nó có thể không hoạt động khi cả hai đều được trả về. Nếu bạn muốn chỉ trả lại một trong số họ, bạn sẽ cần một khóa duy nhất và truy vấn phức tạp hơn.

0

Bất kỳ câu trả lời mà tham gia một bảng trên đó tự sẽ tạo ra một luật vuông ...

- a JOIN b ON a.class = b.class AND a.age >= b.age 
- on average the >= condition will be true for half the class 

- 6 people in a class 
->6*6/2 = 18 

- 10 people in a class 
->10*10/2 = 50 

-> very rapid growth 

Như các kích thước bảng phát triển các hoạt động sẽ làm suy giảm nhanh chóng. Nếu bạn đang giữ mọi thứ nhỏ và chúng sẽ không phát triển nhiều, đó có phải là vấn đề không? Cuộc gọi của bạn có ...

Một thay thế liên quan đến mã nhiều hơn, nhưng tăng tuyến tính ...

  • Đầu tiên, chèn tất cả các hồ sơ intoa bảng mới, với một lĩnh vực SẮC, sắp xếp theo lớp sau đó Tuổi
  • Bây giờ, đối với mỗi lớp, tìm MIN (id)
  • Bây giờ, đối với mỗi lớp, rinf kỷ lục ở đâu = MIN (id) + 8 (đối với cả 9)

có rất nhiều cách thực hiện 2 bước cuối cùng. Cá nhân tôi sẽ sử dụng ...

SELECT 
    [USER_WITH_IDS].id, 
    [USER_WITH_IDS].class, 
    [USER_WITH_IDS].age 
FROM 
    [USER_WITH_IDS] 
WHERE 
    [USER_WITH_IDS].id = (
          SELECT 
           MIN([min].ID) + 8 
          FROM 
           [USER_WITH_IDS] AS [min] 
          WHERE 
           [min].class = [USER_WITH_IDS].class 
         ) 

Điều này mang lại cho ...

  • Một đường chuyền để tạo ra các ID mới
  • Một đường chuyền để có được MIN (id) cho mỗi lớp
  • Một đường chuyền để có được những hồ sơ bạn cần

  • Và tùy thuộc vào cách tốt người tối ưu hóa là, bằng cách sử dụng một chỉ số (lớp sau đó id) sẽ cho phép nó kết hợp 2 lượt cuối cùng thành 1 vượt qua.

2 hoặc 3 lần, cho dù kích thước của bảng hoặc lớp lớn như thế nào. Tuyến tính, không vuông luật ...

7

đây N trình bày Nth kỷ lục oldest

SELECT * 
FROM users k 
WHERE N = (SELECT 
      COUNT(DISTINCT age) 
      FROM users u 
      WHERE k.age >= u.age 
       AND k.class = u.class 
      GROUP BY u.class) 

và nó mang lại cho Nth kỷ lục youngest

SELECT * 
FROM users k 
WHERE N = (SELECT 
      COUNT(DISTINCT age) 
      FROM users u 
      WHERE k.age <= u.age 
       AND k.class = u.class 
      GROUP BY u.class) 
+0

Bạn tiết kiệm được ngày của tôi, cảm ơn !!!!!! – mzalazar

+0

tuyệt vời !! điều này nên được đánh dấu là câu trả lời –

Các vấn đề liên quan