2013-02-19 26 views
5

tôi đang trải qua SQLZOO "SELECT within SELECT tutorial" và đây là một trong những thắc mắc mà làm công việc (nhiệm vụ)Đây có phải là truy vấn chậm không? Nó có thể được cải thiện không?

thế giới (tên, lục, diện tích, dân số, GDP)

SELECT w1.name, w1.continent, w1.population 
FROM world w1 
WHERE 25000000 >= ALL(SELECT w2.population FROM world w2 WHERE w2.continent=w1.continent) 

Câu hỏi của tôi là về hiệu quả của truy vấn như vậy. Truy vấn con sẽ chạy cho mỗi hàng (quốc gia) của truy vấn chính và do đó liên tục điền lại danh sách ALL cho một lục địa cụ thể.

  1. Tôi có nên quan tâm hoặc sẽ tối ưu hóa Oracle bằng cách nào đó quản lý nó?
  2. Nó có thể được lập trình lại mà không có truy vấn phụ tương quan không?
+0

Dưới đây là một fiddle cho dữ liệu/truy vấn: http://sqlfiddle.com/#!4/2aed1/1 – Wilduck

Trả lời

1

Nếu bạn muốn viết lại truy vấn mà không một subquery correalted, đây là một cách:

SELECT w1.name, w1.continent, w1.population 
FROM world w1 
    JOIN 
    (SELECT continent, MAX(population) AS max_population 
     FROM world 
     GROUP BY continent 
    ) c 
    ON c.continent = w1.continent 
WHERE 25000000 >= c.max_population ; 

Tôi không ngụ ý rằng điều này sẽ nhanh hơn. Trình tối ưu hóa của Oracle khá tốt và đây là một truy vấn tổng thể đơn giản, tuy nhiên bạn viết nó. Đây là một việc đơn giản hóa:

SELECT w1.name, w1.continent, w1.population 
FROM world w1 
    JOIN 
    (SELECT continent 
     FROM world 
     GROUP BY continent 
     HAVING MAX(population) <= 25000000 
    ) c 
    ON c.continent = w1.continent ; 
+0

Tôi thích các giải pháp của bạn (đặc biệt là giải pháp thứ 2). Tôi tin rằng điều này tôi đang tìm kiếm. –

3

Trước hết, bạn cần phải hiểu cách oracle biến đổi truy vấn này để đánh giá.

SELECT w1.name 
    , w1.continent 
    , w1.population 
FROM world w1 
WHERE 25000000 >= ALL(SELECT w2.population 
         FROM world w2 
         WHERE w2.continent=w1.continent 
        ); 

Bây giờ tôi ưu hoa biến đổi một điều kiện mà sử dụng các toán tử so sánh ALL theo sau là một subquery vào một điều kiện tương đương mà sử dụng bất kỳ toán tử so sánh và toán tử so sánh bổ sung

SELECT w1.name 
     , w1.continent 
     , w1.population 
    FROM world w1 
    WHERE NOT(25000000 < ANY (SELECT w2.population 
         FROM world w2 
         WHERE w2.continent=w1.continent) 
     ); 

Các ưu biến đổi sau đó tiếp tục truy vấn thứ hai vào truy vấn sau bằng cách sử dụng quy tắc để chuyển đổi điều kiện với toán tử so sánh ANY, theo sau là truy vấn con tương quan:

SELECT w1.name 
     , w1.continent 
     , w1.population 
    FROM world w1 
    WHERE 
    NOT EXISTS (SELECT w2.population 
        FROM world w2 
       WHERE w2.continent=w1.continent 
        AND 25000000 < w2.population 
       ); 

này tôi đã lấy từ nguồn oracle Link

Đối với câu hỏi của bạn:

  1. Có oracle sẽ chăm sóc này, như việc chuyển đổi cho thấy, làm thế nào oracle chuyển đổi trên query.But hiểu rõ hơn cách cuối này công việc truy vấn kết quả.
  2. có, điều này có thể được thực hiện mà không có truy vấn phụ tương quan, nhưng dù sao bạn phải tham gia cùng một bảng vì bạn cần so sánh các bản ghi khác trong bảng có cùng một lục địa. [Vui lòng sửa tôi nếu tôi sai]
+0

Tôi đã suy nghĩ (nhưng không thể tìm thấy) một giải pháp mà xây dựng một ' danh sách tĩnh của tất cả các lục địa phù hợp với tiêu chí bằng cách đánh giá từng lục địa ** chỉ một lần **. –

1

bạn có thể đơn giản hóa này mà không cần phải quét các bảng hai lần:

select a.name, a.continent, a.population, a.max_pop 
    from (select w1.name, w1.continent, w1.population, 
       max(w1.population) over (partition by w1.continent) max_pop 
      from world w1 
     ) a 
where 25000000 >= a.max_pop; 
Các vấn đề liên quan