2013-02-21 20 views
5

Tôi đang gặp khó khăn trong việc tìm ra cách để Oracle thiếu sự hỗ trợ cho mệnh đề HAVING EVERY.Oracle SQL - có giải pháp HAVING EVERY chuẩn không?

Tôi có hai bảng, sản xuất và Movie, với sơ đồ sau:

Production (pid, mid) 
Movie(mid, director) 

nơi 'pid' là trong số nguyên đại diện cho nhà xuất bản ID, 'giữa' là một số nguyên đại diện cho ID phim, và giám đốc là tên của đạo diễn phim.

Mục tiêu của tôi là nhận danh sách nhà xuất bản (theo ID) chỉ xuất bản các phim do Peter Jackson hoặc Ben Affleck chỉ đạo.

Để đạt được điều này, tôi đã viết các truy vấn sau đây:

SELECT * 
    FROM Production P, Movie M 
    WHERE P.mid = M.mid; 
    GROUP BY P.pid 
    HAVING EVERY (M.director IN ('Ben Affleck', 'Peter Jackson')); 

Nhưng kể từ khi Oracle không hỗ trợ CÓ MỌI, tất cả tôi nhận được là các lỗi sau:

HAVING EVERY (M.director IN ('ben affleck', 'PJ')) 
          * 
ERROR at line 5: 
ORA-00907: missing right parenthesis 

Vì giám đốc phải áp dụng cho mọi bộ phim do nhà xuất bản sản xuất, tôi không tin rằng điều kiện có thể được chuyển sang mệnh đề WHERE.

Có cách nào xung quanh rào cản này không? Bất cứ điều gì được coi là "tiêu chuẩn"? Ngoài ra (và có lẽ quan trọng hơn) tại sao Oracle lại chọn không triển khai HAVING EVERY?

Trả lời

4

Hãy thử điều này:

SELECT P.pid 
FROM (select distinct Pi.pid, M.Director 
     from Production Pi INNER JOIN 
    Movie M ON Pi.mid = M.mid) P 
GROUP BY P.pid 
HAVING sum(case when P.Director in ('Ben Affleck', 'Peter Jackson') 
      then 1 else 99 end) = 2 

Here is a sqlfiddle demo

+1

Đó dường như làm các trick! Cảm ơn rất nhiều. Khi chúng tôi ở đây, bạn có biết tại sao Oracle chưa triển khai HAVING EVERY? Tôi cảm thấy như mã workaround là rất hacky/khó đọc, mà đối với tôi là một khía cạnh rất tiêu cực. – Dan

+1

+1 - Tôi đã xóa câu trả lời của mình khi tôi hiểu lầm yêu cầu OP. Câu trả lời hay! – sgeddes

3

Sau khi suy nghĩ về nó trong một thời gian, tôi đã đưa ra một cái gì đó mà có lẽ nhiều hơn một chút có thể đọc được hơn những gì ABCade đến với:

select distinct P.pid 
    from Production P 
    where P.pid not in (
     -- Get publishers that have produced a movie directed by someone else 
     select P1.pid 
     from Production P1 INNER JOIN Movie M ON P1.mid = M.mid 
     where M.director not in ('Ben Affleck', 'Peter Jackson') 
    ) 

SQLFiddle demo

T khác biệt là, thay vì tìm kiếm các nhà sản xuất chỉ với những đạo diễn mong muốn, chúng tôi xác định tất cả các nhà sản xuất được liên kết với các giám đốc khác và sau đó bỏ qua chúng.

+0

+1 để suy nghĩ bên ngoài hộp! Chỉ downer là subquery tương quan mà sẽ tốn kém trên các tập dữ liệu lớn. Xem câu trả lời của tôi. – ninesided

+0

+1 điều này đơn giản hơn nhiều! –

2

Dựa trên Dan's own answer, nhưng tôi đã loại bỏ các subquery tương quan, vì nó có khả năng sẽ thực hiện rất kém trên tập hợp dữ liệu lớn:

SELECT DISTINCT P.pid 
FROM Production P 
LEFT JOIN (
    SELECT P1.pid 
    FROM Production P1 
    INNER JOIN Movie M ON (P1.mid = M.mid) 
    WHERE M.director NOT IN ('Ben Affleck', 'Peter Jackson') 
) V ON (P.pid = V.pid) 
WHERE v.pid IS NULL; 

SQL Fiddle demo

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