मेरे पास डेटा है जो कुछ ऐसा है:
+------------+---------+-------+
| Name | Time | Flag |
+------------+---------+-------+
| Bob | 401 | 1 |
| Bob | 204 | 0 |
| Dan | 402 | 1 |
| Dan | 210 | 0 |
| Jeff | 204 | 0 |
| Fred | 407 | 1 |
| Mike | 415 | 1 |
| Mike | 238 | 0 |
+------------+---------+-------+
मैं प्रत्येक व्यक्ति का सर्वश्रेष्ठ समय प्राप्त करना चाहता हूं, लेकिन यदि "झंडा" सेट है, तो उनके समय को 2 से विभाजित किया जाना चाहिए। उदाहरण के लिए, बॉब का सबसे अच्छा समय 200.5 होगा।
अब मैं इस डेटा को इस तरह प्राप्त करने के लिए अपेक्षाकृत सरल क्वेरी कर सकता हूं:
SELECT userid,
MIN(CASE WHEN flag = 1 THEN time / 2 ELSE time END) AS convertedTime,
time,
flag
FROM times t
GROUP BY userid
ORDER BY convertedtime ASC
यहां समस्या यह है कि यह डेटा प्राप्त करने के लिए समय और ध्वज के लिए उचित संबंधित डेटा वापस नहीं करता है:
Bob 200.5 204 0
सही डेटा के बजाय
Bob 200.5 401 1
बेशक मैं पिछली क्वेरी के साथ समस्या देखता हूं और मैंने इसे इसके साथ ठीक कर दिया है:
SELECT userid,
MIN(convertedtime) AS convertedTime,
(SELECT time
FROM times
WHERE MIN(convertedtime) = CASE
WHEN flag = 1 THEN time / 2
ELSE time
end
LIMIT 1) AS time,
(SELECT flag
FROM times
WHERE MIN(convertedtime) = CASE
WHEN flag = 1 THEN time / 2
ELSE time
end
LIMIT 1) AS flag
FROM (SELECT userid,
CASE
WHEN flag = 1 THEN time / 2
ELSE time
end AS convertedTime,
time,
flag
FROM times t) AS t
GROUP BY userid
ORDER BY convertedtime ASC
यह काम करता है, लेकिन मुझे लगता है कि ऐसा करने का एक बेहतर और अधिक कुशल तरीका होना चाहिए। मेरी वास्तविक क्वेरी में, जिस हिस्से में मैं समय को 2 से विभाजित कर रहा हूं वह बहुत लंबा फॉर्मूला है और मेरे पास हजारों पंक्तियां हैं इसलिए यह बहुत धीमी है।
तो सवाल यह है कि क्या इसके लिए कोई बेहतर/अधिक कुशल प्रश्न है?
2 जवाब
SQL से एक सामान्य तकनीक का उपयोग करें केवल चयन करें कॉलम पर अधिकतम मान वाली पंक्तियाँ लेकिन ON
स्थिति में मानों की तुलना करते समय flag
चेक जोड़ें।
SELECT t1.username, t2.convertedtime, t1.time, t1.flag
FROM times AS t1
JOIN (SELECT username,
MIN(IF(flag = 1, time/2, time) AS convertedtime
FROM times
GROUP BY username) AS t2
ON t1.username = t2.username
AND t1.time = IF(t1.flag = 1, t2.convertedtime * 2, t2.convertedtime)
यह शायद बहुत कुशल नहीं होगा - मुझे नहीं लगता कि यह सशर्त तुलना के लिए एक इंडेक्स का उपयोग करने में सक्षम होगा।
यही वह है जिसका मैंने उपयोग करके समाप्त किया (इस मामले में संख्या को वापस करने के लिए 2 से गुणा नहीं किया जा सकता है क्योंकि इसमें मेरी अधिक जटिल वास्तविक क्वेरी गोल हो रही है), लेकिन बरमार ने वही काम किया जैसा मैं कर रहा हूं इसलिए मैंने चिह्नित किया उसके उत्तर के रूप में।
SELECT times.userID, times2.convertedTime, times.time, times.flag
FROM times JOIN
(
SELECT userid,
MIN(CASE WHEN flag = 1 THEN time / 2 ELSE time END) AS convertedTime,
time,
flag
FROM times t
GROUP BY userid
ORDER BY convertedtime ASC
) as times2 ON times.userid = times2.userid AND
(
(times.time / 2 = times2.convertedTime AND times.flag = 1) OR
(times.time = times2.convertedTime AND times.flag = 0)
)
संबंधित सवाल
नए सवाल
mysql
MySQL एक फ्री, ओपन सोर्स रिलेशनल डेटाबेस मैनेजमेंट सिस्टम (RDBMS) है जो स्ट्रक्चर्ड क्वेरी लैंग्वेज (SQL) का उपयोग करता है। इस टैग को अन्य DBs जैसे SQL Server, SQLite आदि के लिए उपयोग न करें। वे विभिन्न DB हैं जो सभी डेटा का प्रबंधन करने के लिए SQL की अपनी बोलियों का उपयोग करते हैं।