2010-06-22 52 views
6

Tôi đang cố gắng tạo ra một bảng kết quả với ngày khóa học đã hoàn thành cuối cùng cho mỗi mã khóa học, cũng như mã khóa học hoàn thành cuối cùng cho mỗi nhân viên . Dưới đây là câu hỏi của tôi:MAX() và MAX() TRÊN TÙY CHỌN bằng cách tạo lỗi 3504 trong Truy vấn Teradata

SELECT employee_number, 
     MAX(course_completion_date) 
      OVER (PARTITION BY course_code) AS max_course_date, 
     MAX(course_completion_date) AS max_date 
FROM employee_course_completion 
WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
GROUP BY employee_number 

truy vấn này tạo ra các lỗi sau:

3504 : Selected non-aggregate values must be part of the associated group 

Nếu tôi loại bỏ các MAX() OVER (PARTITION BY ...) dòng, truy vấn thực hiện tốt, vì vậy Tôi đã bị cô lập vấn đề với dòng đó, nhưng sau khi tìm kiếm các diễn đàn và internet tôi không thể nhìn thấy những gì tôi đang làm sai. Có ai giúp được không?

+0

Bởi vì bạn đang sử dụng VỀ với tham chiếu đến MAX, SQL thấy những như chức năng phân tích - không phải tổng hợp. –

Trả lời

4

Như Ponies nói trong nhận xét, bạn không thể kết hợp các hàm OLAP với hàm tổng hợp.

Có lẽ sẽ dễ dàng hơn để có được ngày hoàn thành cuối cùng cho mỗi nhân viên và tham gia vào tập dữ liệu chứa ngày hoàn thành cuối cùng cho từng khóa học được nhắm mục tiêu.

Đây là một ý tưởng chưa được kiểm tra rằng hy vọng sẽ đưa bạn xuống con đường đúng đắn:

SELECT employee_number, 
     course_code, 
     MAX(course_completion_date) AS max_date, 
     lcc.LAST_COURSE_COMPLETED 
    FROM employee_course_completion ecc 
     LEFT JOIN (
      SELECT employee_number, 
        MAX(course_completion_date) AS LAST_COURSE_COMPLETED 
       FROM employee_course_completion 
       WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
     ) lcc 
     ON lcc.employee_number = ecc.employee_number 
    WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
GROUP BY employee_number, course_code, lcc.LAST_COURSE_COMPLETED 
1

Tôi biết đây là một câu hỏi rất cũ, nhưng tôi đã được yêu cầu bởi người khác một cái gì đó tương tự.

Tôi không có TeraData, nhưng bạn không thể làm như sau?

SELECT employee_number, 
     course_code, 
     MAX(course_completion_date)          AS max_course_date, 
     MAX(course_completion_date) OVER (PARTITION BY employee_number) AS max_date 
FROM employee_course_completion 
WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
GROUP BY employee_number, course_code 

GROUP BY hiện đảm bảo một hàng cho mỗi khóa học cho mỗi nhân viên. Điều này có nghĩa là bạn chỉ cần MAX() thẳng để nhận số max_course_date.

Trước khi GROUP BY chỉ cho một hàng cho mỗi nhân viên và MAX() OVER() đang cố gắng cung cấp nhiều kết quả cho một hàng (mỗi một khóa học).

Thay vào đó, bây giờ bạn cần mệnh đề OVER() để nhận được số MAX() cho toàn bộ nhân viên. Điều này bây giờ là hợp pháp vì mỗi hàng riêng lẻ chỉ nhận được một câu trả lời (vì nó có nguồn gốc từ một siêu thiết lập, không phải là một tập con). Ngoài ra, với cùng một lý do, mệnh đề OVER() bây giờ đề cập đến một giá trị vô hướng hợp lệ, như được xác định bởi mệnh đề GROUP BY; employee_number.


Có lẽ một cách ngắn nói điều này sẽ là một aggregate với một khoản OVER() phải là một siêu tập hợp các GROUP BY, không phải là một tiểu thiết lập.

Tạo truy vấn của bạn bằng GROUP BY ở cấp đại diện cho các hàng bạn muốn, sau đó chỉ định các mệnh đề OVER() nếu bạn muốn tổng hợp ở cấp cao hơn.

+0

Điều này cũng sẽ tạo ra thông báo lỗi tương tự. Các hàm OLAP hợp lý được tính ** sau ** GROUP bY/HAVING, vì vậy bạn chỉ có thể truy cập các cột trong GROUP BY hoặc các cột có hàm tổng hợp. Sau đây có vẻ lạ, nhưng là chuẩn SQL: ** MAX (MAX (course_completion_date)) OVER (PARTITION BY employee_number) ** Và như Teradata cho phép tái sử dụng một bí danh này cũng hoạt động: ** MAX (max_course_date) OVER (PARTITION BY employee_number) ** – dnoeth

1

Chức năng OLAP hợp lý được tính sau GROUP BY/HAVING, vì vậy bạn chỉ có thể truy cập các cột trong GROUP BY hoặc cột có chức năng tổng hợp.Sau vẻ lạ, nhưng là tiêu chuẩn SQL:

SELECT employee_number, 
     MAX(MAX(course_completion_date)) 
      OVER (PARTITION BY course_code) AS max_course_date, 
     MAX(course_completion_date) AS max_date 
FROM employee_course_completion 
WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
GROUP BY employee_number, course_code 

Và như Teradata cho phép tái sử dụng một bí danh này cũng làm việc:

SELECT employee_number, 
     MAX(max_date) 
      OVER (PARTITION BY course_code) AS max_course_date, 
     MAX(course_completion_date) AS max_date 
FROM employee_course_completion 
WHERE course_code IN ('M910303', 'M91301R', 'M91301P') 
GROUP BY employee_number, course_code 
+0

Bạn đã nói rằng các hàm ** olap ** được tính sau ** nhóm bởi/có **, nhưng trong mã trên bạn đang sử dụng 'course_code' trong mệnh đề phân vùng, không phải là một phần của * * Nhóm theo mệnh đề **. Đoạn mã trên không hoạt động trong oracle. Lỗi là 'ORA-00979: không phải là biểu thức GROUP BY' – frank

+0

@frank: Đúng, 'course_code' phải được thêm vào' GROUP BY' – dnoeth

+0

nhờ xác nhận. Tính năng phân tích mới không chắc chắn nếu tôi đã đúng. – frank

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