2010-10-14 47 views
5

Tuyên bố từ chối: Tôi là một newb SQL và đây là một lớp, nhưng tôi thực sự có thể sử dụng một hướng đi đúng hướng.Các giới hạn của GROUP BY

Tôi đã có ba bảng:

student(_sid_, sname, sex, age, year, gpa)
section(_dname_, _cno_, _sectno_, pname)
enroll(_sid_, grade, _dname_, _cno_, _sectno_)
(khóa chính ký hiệu bằng dấu gạch dưới)

Tôi đang cố gắng để viết một truy vấn SQL Oracle tương thích trả về một bảng có tên của học sinh (student.sname) có gpa cao nhất trong mỗi phần (bao gồm section.cnosection.sectno) cũng như tất cả các thuộc tính khác từ section.

tôi đã quản lý để sử dụng một truy vấn tổng hợp và GROUP BY để có được điểm trung bình tối đa cho mỗi phần:

SELECT MAX(s.gpa), e.cno, e.sectno 
    FROM enroll e, 
     student s 
    WHERE s.sid = e.sid 
GROUP BY e.cno, e.sectno 

Hãy để một mình các section thuộc tính khác, tôi thậm chí không thể tìm ra cách để tack trên tên sinh viên (student.sname). Nếu tôi thêm nó vào mệnh đề SELECT, nó phải được bao gồm trong GROUP BY, điều này sẽ làm rối loạn phần còn lại của truy vấn. Nếu tôi sử dụng toàn bộ truy vấn này trong mệnh đề WHERE hoặc FROM của truy vấn bên ngoài, tôi chỉ có thể truy cập vào ba trường trong bảng, điều này không được sử dụng nhiều.

Tôi biết bạn không thể cho tôi câu trả lời chính xác, nhưng mọi gợi ý sẽ được đánh giá cao!

+4

@OMG Ngựa vằn: Tôi thích cách bạn định dạng truy vấn. – JoshD

+0

@JoshD: tất cả chúng ta đều làm ;-) – zerkms

+0

Về cơ bản bạn đã nói điều đó. Thêm bảng mục vào FROM. Thêm các ràng buộc vào phần WHERE để tham gia để đăng ký. Thêm các cột bạn muốn hiển thị cho SELECT và lặp lại chúng trong GROUP BY. – kevpie

Trả lời

3

Giả sử Oracle 9i +, để có được chỉ là một trong những sinh viên có điểm trung bình cao nhất (trong trường hợp quan hệ) sử dụng:

WITH summary AS (
    SELECT e.*, 
      s.name, 
      ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno 
           ORDER BY s.gpa DESC) AS rank 
    FROM ENROLL e 
    JOIN STUDENT s ON s.sid = e.sid) 
SELECT s.* 
    FROM summary s 
WHERE s.rank = 1 

Non CTE tương đương:

SELECT s.* 
    FROM (SELECT e.*, 
       s.name, 
       ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno 
            ORDER BY s.gpa DESC) AS rank 
      FROM ENROLL e 
      JOIN STUDENT s ON s.sid = e.sid) s 
WHERE s.rank = 1 

Nếu bạn muốn xem tất cả sinh viên gắn với GPA, sử dụng:

WITH summary AS (
    SELECT e.*, 
      s.name, 
      DENSE_RANK OVER(PARTITION BY e.cno, e.sectno 
           ORDER BY s.gpa DESC) AS rank 
    FROM ENROLL e 
    JOIN STUDENT s ON s.sid = e.sid) 
SELECT s.* 
    FROM summary s 
WHERE s.rank = 1 
1

Gợi ý: hãy xem xét rằng có thể có nhiều hơn một sinh viên có điểm trung bình cao nhất trong một lớp học. Truy vấn bên ngoài chỉ cần ba trường.

0

lẽ ngắn nhất:

SELECT DISTINCT e.cno, e.sectno , e..., 
     FIRST_VALUE(s.sname) OVER 
           (PARTITION BY e.cno, e.sectno ORDER BY s.gpa DESC) 
FROM enroll e, 
    student s 
WHERE s.sid = e.sid 

Hoặc

SELECT A.* 
FROM 
    ( SELECT s._sid, s.sname, e.cno, e.sectno ,..., s.gpa 
       MAX(s.gpa) OVER (PARTITION BY e.cno, e.sectno) AS maxgpa 
     FROM enroll e, 
      student s 
     WHERE s.sid = e.sid 
    ) A 
WHERE A.maxgpa = A.gpa 
0

Dưới đây là một số gợi ý: -

  1. Bạn đang đi đúng hướng với Nhóm của bạn By truy vấn
  2. lợi nhuận này bạn điểm trung bình tối đa cho mỗi phần dựa trên các trường cno và sectno
  3. Bây giờ, bạn có giá trị GPA tối đa cho mỗi kết hợp cno và sectno.
  4. Sử dụng dữ liệu này mà bạn có một cách ngược lại nếu bạn muốn tìm tất cả các sinh viên phù hợp với các giá trị kết hợp này. GỢI Ý: Xem xét kết quả của Nhóm bạn By truy vấn dưới dạng bảng và Sử dụng một INNER JOIN
  5. Ngay cả Nếu có thể là có nhiều hơn 1 sinh viên cho cùng max GPA, bạn vẫn sẽ nhận được tất cả chúng

Hy vọng điều này sẽ giúp !!

0

Điều này sẽ cung cấp cho bạn những gì bạn đang tìm kiếm. Xem hàm RANK() của Oracle để biết chi tiết về cách GPA được xếp hạng từ cao nhất đến thấp nhất theo phần.

Yêu cầu:

Return một bảng với tên của học sinh (student.sname) mà có GPA cao nhất trong mỗi phần (section.cno và section.sectno) cũng như tất cả các thuộc tính khác từ phần .

SELECT * FROM 
(
    SELECT 
     s.sname, 
     s.gpa, 
     sec.dname, 
     sec.cno, 
     sec.sectno, 
     sec.pname, 
     /* for each "sec.cno, sec.sectno", this will rank each GPA in order from highest to lowest. Ties will have the same rank. */ 
     RANK() OVER(PARTITION BY sec.cno, sec.sectno ORDER BY s.gpa DESC) as r_rank 
    FROM 
     enroll e, 
     student s, 
     section sec 
    WHERE 
     /* join enroll with student */ 
     s.sid = e.sid 
     /* join section with enroll */ 
     AND sec.dname = e.dname 
     AND sec.cno = e.cno 
     AND sec.sectno = e.sectno 
) 
WHERE r_rank = 1 /* this returns only the highest GPA (maybe multiple students) for each "sec.cno, sec.sectno" combination */ 
; 

Lưu ý: Nếu bạn không muốn mối quan hệ, thay đổi RANK() để ROW_NUMBER()

0

Mặc dù đây được trả lời dài trở lại nhưng tôi vẫn muốn trình bày một beautiful explanation, điều này rất hữu ích cho newbie. Ngoài ra Introduction to SQL có các quy tắc như vậy.