2008-09-11 37 views
19

Bạn sẽ chứng minh rằng hai truy vấn có chức năng tương đương, ví dụ như chúng sẽ luôn trả về cùng một tập kết quả.Chứng minh truy vấn SQL tương đương


Như tôi đã có một truy vấn cụ thể trong tâm trí khi tôi đã làm điều này, tôi đã kết thúc làm như @dougman gợi ý, hơn khoảng 10% hàng các bảng có liên quan và so sánh kết quả, đảm bảo không có ra khỏi đặt kết quả.

+0

Tôi giả sử bạn có nghĩa là tập hợp kết quả chính xác. Điều đó có nghĩa là các cột giống nhau (và cùng một kiểu dữ liệu) với cùng một dữ liệu hàng. Chính xác? – Craig

+0

Đúng, đúng vậy Craig –

Trả lời

12

Điều tốt nhất bạn có thể làm là so sánh 2 kết quả đầu ra truy vấn dựa trên tập hợp các đầu vào tìm kiếm bất kỳ sự khác biệt nào. Để nói rằng họ sẽ luôn luôn trả lại kết quả tương tự cho tất cả các yếu tố đầu vào thực sự phụ thuộc vào dữ liệu.

Đối với Oracle một trong những cách tiếp cận tốt hơn nếu không tốt nhất (rất hiệu quả) là ở đây (Ctrl + F So sánh nội dung của hai bảng):
http://www.oracle.com/technetwork/issue-archive/2005/05-jan/o15asktom-084959.html

nào nắm tới:

select c1,c2,c3, 
     count(src1) CNT1, 
     count(src2) CNT2 
    from (select a.*, 
       1 src1, 
       to_number(null) src2 
      from a 
     union all 
     select b.*, 
       to_number(null) src1, 
       2 src2 
      from b 
     ) 
group by c1,c2,c3 
having count(src1) <> count(src2); 
+1

Cập nhật liên kết: http://www.oracle.com/technetwork/issue-archive/2005/05-jan/o15asktom-084959.html – MyDogTom

8

Điều này nghe với tôi giống như một vấn đề hoàn chỉnh NP. Tôi không chắc chắn có một cách chắc chắn để chứng minh loại điều này

1

Các nhà cung cấp DBMS đã làm việc này trong một thời gian rất, rất dài. Như Rik đã nói, đó là có thể là một vấn đề khó xử, nhưng tôi không nghĩ rằng bất kỳ phân tích chính thức nào về NP-đầy đủ của không gian vấn đề đã được thực hiện.

Tuy nhiên, đặt cược tốt nhất của bạn là tận dụng DBMS càng nhiều càng tốt. Tất cả các hệ thống DBMS dịch SQL thành một số loại kế hoạch truy vấn. Bạn có thể sử dụng kế hoạch truy vấn này, đây là một phiên bản trừu tượng của truy vấn, là điểm khởi đầu tốt (DBMS sẽ làm rất nhiều tối ưu hóa, làm phẳng các truy vấn thành các mô hình khả thi hơn).

LƯU Ý: DBMS hiện đại sử dụng trình phân tích "dựa trên chi phí" không xác định qua các cập nhật thống kê, do đó, người lập kế hoạch truy vấn có thể thay đổi kế hoạch truy vấn cho các truy vấn giống hệt nhau.

Trong Oracle (tùy thuộc vào phiên bản của bạn), bạn có thể yêu cầu trình tối ưu hóa chuyển từ trình phân tích dựa trên chi phí sang phân tích dựa trên quy tắc xác định (điều này sẽ đơn giản hóa phân tích kế hoạch) với gợi ý SQL, ví dụ:

SELECT /*+RULE*/ FROM yourtable 

Trình tối ưu hóa dựa trên quy tắc đã không được dùng vì 8i nhưng vẫn bị treo xung quanh 10g (Tôi không biết 'bout 11). Tuy nhiên, bộ phân tích dựa trên quy tắc ít phức tạp hơn nhiều: tỷ lệ lỗi có khả năng cao hơn nhiều.

Để đọc thêm về bản chất chung chung hơn, IBM đã khá sung mãn với bằng sáng chế tối ưu hóa truy vấn của họ. Điều này ở đây trên một phương pháp để chuyển đổi SQL thành "kế hoạch trừu tượng" là một điểm khởi đầu tốt: http://www.patentstorm.us/patents/7333981.html

0

Bạn không.

Nếu bạn cần một mức độ tin cậy cao rằng thay đổi hiệu suất, ví dụ, không thay đổi kết quả của truy vấn, sau đó kiểm tra địa ngục.

Nếu bạn cần một mức độ tin cậy thực sự cao .. sau đó errrm, kiểm tra nó nhiều hơn.

Kiểm tra mức độ lớn không phải là khó để cobble cùng nhau cho một truy vấn SQL. Viết một proc sẽ lặp lại xung quanh một tập hợp lớn/đầy đủ các paramenters có thể, và gọi mỗi truy vấn với mỗi bộ params, và viết các kết quả đầu ra cho các bảng tương ứng. So sánh hai bảng và ở đó bạn có nó.

Nó không chính xác khoa học, mà tôi đoán là câu hỏi của OP, nhưng tôi không biết một phương pháp chính thức để chứng minh sự tương đương.

1

Có lẽ bạn có thể rút ra (bằng tay) truy vấn của mình và kết quả bằng cách sử dụng Venn Diagrams và xem liệu chúng có tạo ra cùng một biểu đồ hay không. Các sơ đồ Venn rất tốt cho các bộ dữ liệu đại diện, và các truy vấn SQL hoạt động trên các bộ dữ liệu. Vẽ ra một sơ đồ Venn có thể giúp bạn hình dung nếu 2 truy vấn có chức năng tương đương.

2

Điều này khá dễ thực hiện.

Cho phép giả định truy vấn của bạn được đặt tên a và b

một trừ b

nên cung cấp cho bạn một tập rỗng. Nếu nó không. sau đó các truy vấn trả về các tập hợp khác nhau và tập kết quả sẽ hiển thị cho bạn các hàng khác nhau.

sau đó làm

b trừ một

mà nên cung cấp cho bạn một tập rỗng. Nếu có, thì các truy vấn sẽ trả về cùng một tập hợp. nếu không trống, thì các truy vấn khác nhau ở một số khía cạnh và tập hợp kết quả sẽ hiển thị cho bạn các hàng khác nhau.

+0

Trong SQL Server, bạn có thể sử dụng EXCEPT cho phương pháp này - http://msdn.microsoft.com/en-us/library/ms188055%28SQL.90%29.aspx –

+3

Điều này chỉ chứng minh sự tương đương cho tập hợp cụ thể đó, không phải cho truy vấn nói chung. – Rik

+0

@ vâng yep ... đó là ý định. tôi nghi ngờ bất cứ ai cũng có thể làm bằng chứng với phép tính quan hệ – EvilTeach

1

Điều này sẽ thực hiện thủ thuật. Nếu truy vấn này trả về 0 hàng thì hai truy vấn sẽ trả về cùng một kết quả. Như một phần thưởng, nó chạy như một truy vấn đơn, do đó bạn không phải lo lắng về việc thiết lập mức cô lập sao cho dữ liệu không thay đổi giữa hai truy vấn.

select * from ((<query 1> MINUS <query 2>) UNION ALL (<query 2> MINUS <query 1>)) 

Dưới đây là một kịch bản shell tiện dụng để làm điều này:

#!/bin/sh 

CONNSTR=$1 
echo query 1, no semicolon, eof to end:; Q1=`cat` 
echo query 2, no semicolon, eof to end:; Q2=`cat` 

T="(($Q1 MINUS $Q2) UNION ALL ($Q2 MINUS $Q1));" 

echo select 'count(*)' from $T | sqlplus -S -L $CONNSTR 
0

cẩn thận! Chức năng "tương đương" thường dựa trên dữ liệu và bạn có thể "chứng minh" tương đương 2 truy vấn bằng cách so sánh kết quả cho nhiều trường hợp và vẫn sai khi dữ liệu thay đổi theo cách nhất định.

Ví dụ:

SQL> create table test_tabA 
(
col1 number 
) 

Table created. 

SQL> create table test_tabB 
(
col1 number 
) 

Table created. 

SQL> -- insert 1 row 

SQL> insert into test_tabA values (1) 

1 row created. 

SQL> commit 

Commit complete. 

SQL> -- Not exists query: 

SQL> select * from test_tabA a 
where not exists 
(select 'x' from test_tabB b 
where b.col1 = a.col1) 

     COL1 

---------- 

     1 

1 row selected. 

SQL> -- Not IN query: 

SQL> select * from test_tabA a 
where col1 not in 
(select col1 
from test_tabB b) 

     COL1 

---------- 

     1 

1 row selected. 


-- THEY MUST BE THE SAME!!! (or maybe not...) 


SQL> -- insert a NULL to test_tabB 

SQL> insert into test_tabB values (null) 

1 row created. 

SQL> commit 

Commit complete. 

SQL> -- Not exists query: 

SQL> select * from test_tabA a 
where not exists 
(select 'x' from test_tabB b 
where b.col1 = a.col1) 


     COL1 

---------- 

     1 

1 row selected. 

SQL> -- Not IN query: 

SQL> select * from test_tabA a 
where col1 not in 
(select col1 
from test_tabB b) 

**no rows selected.** 
2

Bạn thực sự nên kiểm tra Cosette: Nó kiểm tra (với một bằng chứng) nếu 2 SQL truy vấn của tương đương và truy cập ví dụ khi không tương đương. Đó là cách duy nhất để hoàn toàn chắc chắn, gần như vậy;) Bạn thậm chí có thể ném vào 2 truy vấn trên trang web của họ và kiểm tra (chính thức) tương đương ngay lập tức.

Liên kết với Cosette: http://cosette.cs.washington.edu/

Liên kết đến bài viết mà đưa ra một lời giải thích tốt về cách Cosette hoạt động: https://medium.com/@uwdb/introducing-cosette-527898504bd6

Nếu tất cả các bạn muốn chỉ là một sửa chữa thực tế nhanh chóng, bạn cũng có thể kiểm tra câu trả lời stackoverflow này : [sql - check if two select's are equal]

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