2012-04-16 10 views
19

मैं एक सरल और विस्तारित तरीके से यह question फिर से पूछ रहा हूं। जहाँ तक मेरा बता सकते हैं, mysql केMySQL और sqlite के बीच चयन परिणाम क्यों भिन्न होते हैं?

+------+--------+ 
| id | avg1 | 
+------+--------+ 
| 106 | 4.5000 | 
+------+--------+ 

:

create table foo (id INT, score INT); 

insert into foo values (106, 4); 
insert into foo values (107, 3); 
insert into foo values (106, 5); 
insert into foo values (107, 5); 

select T1.id, avg(T1.score) avg1 
from foo T1 
group by T1.id 
having not exists (
    select T2.id, avg(T2.score) avg2 
    from foo T2 
    group by T2.id 
    having avg2 > avg1); 

SQLite का उपयोग करना, select बयान रिटर्न:

id   avg1  
---------- ---------- 
106   4.5  
107   4.0  

और mysql रिटर्न

इन एसक्यूएल बयान पर विचार करें परिणाम सही हैं, और एसक्लाइट गलत हैं। मैं निम्नलिखित के रूप में SQLite साथ real को कास्ट करने के लिए करने की कोशिश की लेकिन यह अभी भी दो रिकॉर्ड रिटर्न:

select T1.id, cast(avg(cast(T1.score as real)) as real) avg1 
from foo T1 
group by T1.id 
having not exists (
    select T2.id, cast(avg(cast(T2.score as real)) as real) avg2 
    from foo T2 
    group by T2.id 
    having avg2 > avg1); 

क्यों SQLite वापसी दो रिकॉर्ड?

त्वरित अद्यतन:

मैं नवीनतम SQLite संस्करण (3.7.11) और अभी भी दो रिकॉर्ड मिल के खिलाफ बयान भाग गया।

कोई अन्य अपडेट:

मैं इस मुद्दे के बारे में [email protected] को एक ईमेल भेजा।

स्वयं, मैं वीडीबीई के साथ खेल रहा हूं और कुछ दिलचस्प पाया है। मैंने not exists (प्रत्येक औसत समूह के लिए एक) के प्रत्येक लूप के निष्पादन ट्रेस को विभाजित किया।

create table foo (id VARCHAR(1), score INT); 

insert into foo values ('c', 1.5); 
insert into foo values ('b', 5.0); 
insert into foo values ('a', 4.0); 
insert into foo values ('a', 5.0); 

PRAGMA vdbe_listing = 1; 
PRAGMA vdbe_trace=ON; 

select avg(score) avg1 
from foo 
group by id 
having not exists (
    select avg(T2.score) avg2 
    from foo T2 
    group by T2.id 
    having avg2 > avg1); 

हम स्पष्ट रूप से देख कि किसी भी तरह क्या होना चाहिए r:4.5i:5 बन गया है::

तीन औसत समूहों करवाने के लिए, मैं निम्नलिखित बयानों का इस्तेमाल किया

enter image description here

मैं अब कोशिश कर रहा हूँ यह देखने के लिए कि क्यों है।

अंतिम संपादित:

तो मैं SQLite स्रोत कोड के साथ पर्याप्त खेल रहा है। मैं जानवर काफी बेहतर अब समझते हैं, हालांकि मैं original developer तरह इसे बाहर दूँगा के रूप में वह पहले से ही यह कर किया जा रहा है:

http://www.sqlite.org/src/info/430bb59d79

दिलचस्प है, मुझे कम से कम करने के लिए, ऐसा लगता है कि नए संस्करण (संस्करण मैं उपयोग कर रहा हूँ के बाद कुछ समय) एक से अधिक रिकॉर्ड डालने का समर्थन करता है के रूप में एक परीक्षण का मामला ऊपर उल्लिखित में जोड़ा में इस्तेमाल के लिए प्रतिबद्ध:

CREATE TABLE t34(x,y); 
INSERT INTO t34 VALUES(106,4), (107,3), (106,5), (107,5); 
+0

बस किक के लिए मैं एसक्यूएल को यह चलाया, तो SQL सर्वर का उत्पादन होगा और यह 'शिकायत की avg2' और' avg1' मौजूद नहीं था। मैंने उन्हें 'MAX (T2.score) 'और' MAX (T1.score)' के साथ बदल दिया और यह SQLite परिणाम दिया। जब मैंने 'स्कोर रीयल' के साथ तालिका बनाई तो उसने MySQL परिणाम दिया। शायद आपकी MySQL स्कीमा sqlites के लिए अलग है? –

+0

@ ta.speot.is: क्या आप avg2' (दो मौके) के रूप में 'avg (T2.score) में' as' जोड़ने का प्रयास कर सकते हैं? –

+0

काम नहीं करता है। जब भी 'WHERE', 'GROUP BY' या' HAVING' में उपनामों का उपयोग करने की बात आती है तो निश्चित रूप से SQL सर्वर पासा नहीं चलाता है। –

उत्तर

1

मैं क्वेरी के कुछ भिन्न रूपों के साथ गड़बड़ करने की कोशिश की।

ऐसा लगता है, जैसे स्क्लाइट में पिछले घोषित फ़ील्ड का उपयोग नेस्टेड हैविंग अभिव्यक्तियों में त्रुटियों में है।

अपने उदाहरण avg1 में दूसरा होने के तहत हमेशा के बराबर है 5.0

देखो:

select T1.id, avg(T1.score) avg1 
from foo T1 
group by T1.id 
having not exists (
    SELECT 1 AS col1 GROUP BY col1 HAVING avg1 = 5.0); 

यह एक कुछ भी नहीं देता है, लेकिन इस क्वेरी का निष्पादन दोनों रिकॉर्ड रिटर्न:

... 
having not exists (
    SELECT 1 AS col1 GROUP BY col1 HAVING avg1 <> 5.0); 

मुझे sqlite tickets list पर कोई भी समान बग नहीं मिल रहा है।

+1

हां मैं वीडीबीई के साथ ट्रेसिंग के साथ कुछ बहुत समान दिख रहा हूं। मैंने पहले से ही इस मुद्दे के बारे में एक ईमेल [email protected] भेजा है। –

0

क्या आपने इस संस्करण को आजमाया है? : (एक ही परिणाम दे दिया जाना चाहिए जो)

select T1.id, avg(T1.score) avg1 
from foo T1 
group by T1.id 
having not exists (
    select T2.id, avg(T2.score) avg2 
    from foo T2 
    group by T2.id 
    having avg(T2.score) > avg(T1.score)); 

इसके अलावा इस एक:

select T1.* 
from 
    (select id, avg(score) avg1 
    from foo 
    group by id 
) T1 
where not exists (
    select T2.id, avg(T2.score) avg2 
    from foo T2 
    group by T2.id 
    having avg(T2.score) > avg1); 

क्वेरी भी HAVING खंड में सबक्वेरी के बजाय, व्युत्पन्न तालिकाओं के साथ संभाला जा सकता है:

select ta.id, ta.avg1 
from 
    (select id, avg(score) avg1 
    from foo 
    group by id 
) ta 
    JOIN 
    (select avg(score) avg1 
    from foo 
    group by id 
    order by avg1 DESC 
    LIMIT 1 
) tmp 
    ON tmp.avg1 = ta.avg1 
+0

मैंने अभी किया; एसक्लाइट में एक ही 2 रिकॉर्ड, mysql में एक ही रिकॉर्ड। –

+0

हां आपका दूसरा विकल्प मैंने पहले से ही एक उत्तर के रूप में कार्य किया है; कृपया इस प्रश्न की शुरुआत में जुड़े प्रश्न को देखें। –

+0

क्यों मूल क्वेरी अपेक्षित के रूप में काम नहीं करती है, मुझे लगता है कि यह एक बग है, कैसे subqueries हैंडल से नियंत्रित किया जाता है। –

1

चलिए देखते हैं इस दो तरीके, मैं होने का 'नहीं' छुटकारा मेरे संदर्भ डेटाबेस

(1)

-- select rows from foo 

select T1.id, avg(T1.score) avg1 
from foo T1 
group by T1.id 
-- where we don't have any rows from T2 
having not exists (
-- select rows from foo 
select T2.id, avg(T2.score) avg2 
from foo T2 
group by T2.id 
-- where the average score for any row is greater than the average for 
-- any row in T1 
having avg2 > avg1); 

id |  avg1   
-----+-------------------- 
106 | 4.5000000000000000 
(1 row) 

तो की, सबक्वेरी अंदर तर्क के कुछ बढ़ते हैं के रूप में postgres 9.0 का उपयोग करेंगे: (2 आप वास्तव में क्या मतलब है जब आप एक होने खंड के अंदर इस सहसंबद्ध सबक्वेरी करते हैं, अगर यह प्राथमिक क्वेरी हम एक कार्तीय कर रहे हैं से प्रत्येक पंक्ति के खिलाफ हर पंक्ति का मूल्यांकन करता है -)

-- select rows from foo 
select T1.id, avg(T1.score) avg1 
from foo T1 
group by T1.id 
-- where we do have rows from T2 
having exists (
-- select rows from foo 
select T2.id, avg(T2.score) avg2 
from foo T2 
group by T2.id 
-- where the average score is less than or equal than the average for any row in T1 
having avg2 <= avg1); 
-- I think this expression will be true for all rows as we are in effect doing a 
--cartesian join 
-- with the 'having' only we don't display the cartesian row set 

id |  avg1   
-----+-------------------- 
106 | 4.5000000000000000 
107 | 4.0000000000000000 
(2 rows) 

ताकि आप अपने आप से पूछना करने के लिए मिल गया है शामिल हों और मुझे नहीं लगता कि हमें उंगली को इंगित करना चाहिए एसक्यूएल इंजन पर आरएस।

यदि आप हर पंक्ति है कि अधिकतम औसत से भी कम है चाहता हूँ क्या आप कह जाना चाहिए:

select T1.id, avg(T1.score) avg1 
from foo T1 group by T1.id 
having avg1 not in 
(select max(avg1) from (select id,avg(score) avg1 from foo group by id)) 
+0

मेरे प्रश्न में यह चुनिंदा बयान वास्तव में समझना मुश्किल नहीं है; मैं बस सही परिणाम चाहता हूं ;-) –

+0

मेरा तर्क है कि यह संदिग्ध है और विभिन्न प्रौद्योगिकियों में एक अनिश्चित परिणाम प्रदान करेगा –

+0

ऐसा लगता है कि यह माइस्क्ल, एमएस एसक्यूएल, और अब पोस्टग्रेस से संदिग्ध नहीं है; और ऐसा लगता है कि स्क्लाइट का मुख्य डेवलपर [email protected] पर भेजे गए ईमेल की प्रतिक्रिया में बदलाव कर रहा है। –