अपने मूल पर निर्माण
आपकी मूल क्वेरी आपत्तिजनक पंक्तियों को बाहर करने के लिए सही रास्ते पर थी। आपके पास बस >
था =
. के बजाय . गिनने का मुश्किल कदम गायब था।
SELECT count(*) AS ct
FROM (
SELECT 1
FROM compatibility c
WHERE rating_id = 1
AND NOT EXISTS (
SELECT 1
FROM compatibility c2
WHERE c2.rating_id > 1
AND (c2.attr1_id = c.attr1_id AND c2.attr2_id = c.attr2_id OR
c2.attr1_id = c.attr2_id AND c2.attr2_id = c.attr1_id))
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
) sub;
छोटा
शायद तेज़ भी।
SELECT count(*) AS ct
FROM (
SELECT 1 -- selecting more columns for count only would be a waste
FROM compatibility
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
HAVING every(rating_id = 1)
) sub;
@Clodoaldo's query
के समान या यह अधिक स्पष्टीकरण के साथ पूर्व उत्तर
.every(rating_id = 1)
not bool_or(rating_id > 1)
, लेकिन इसमें rating < 1
. भी शामिल नहीं है - जो आपके मामले के लिए शायद ठीक (या इससे भी बेहतर) है।
MySQL वर्तमान में लागू नहीं होता (मानक SQL!) every()
. चूंकि आप केवल rating_id > 1
. को हटाना चाहते हैं , यह सरल अभिव्यक्ति आपकी आवश्यकताओं को अधिक बारीकी से फिट करती है और RDBMS दोनों में काम करती है:
HAVING max(rating_id) = 1
सबसे छोटा
count(*)
. के साथ विंडो एग्रीगेट फ़ंक्शन के रूप में और सबक्वेरी के बिना।
SELECT count(*) OVER () AS ct
FROM compatibility
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
HAVING max(rating_id) = 1
LIMIT 1;
विंडो फ़ंक्शन बाद लागू होते हैं कुल कदम। इस पर निर्माण करते हुए हमें दो मिलता है एकल क्वेरी स्तर में किए गए कुल चरण:
- बराबर मोड़ो
(atr1_id, atr2_id)
, उन पंक्तियों को छोड़कर जहां भिन्नrating_id
मौजूद है। - पूरे सेट पर विंडो फ़ंक्शन के साथ शेष पंक्तियों की गणना करें।
LIMIT 1
एकल पंक्ति प्राप्त करने के लिए (सभी पंक्तियाँ समान होंगी)।
MySQL में विंडो फ़ंक्शन नहीं हैं। पोस्टग्रेज केवल.
सबसे छोटा, जरूरी नहीं कि सबसे तेज़।
SQL Fiddle. (pg9.2 पर क्योंकि pg9.3 अभी ऑफलाइन है।)