MySQL की एक विशेषता के कारण, आपने गलत समझा है कि SQL में GROUP BY कैसे काम करता है। मानक एसक्यूएल में सेलेक्ट स्टेटमेंट में हर नॉन एग्रीगेट कॉलम ग्रुप बाय क्लॉज में होना चाहिए (कॉलम के लिए एक अपवाद है जिसका मान ग्रुप बाय क्लॉज में पहले से मौजूद कॉलम पर 100% निर्भर है, हालांकि एसक्यूएल के कुछ फ्लेवर इस छूट का समर्थन करते हैं) ।
MySQL इसे डिफ़ॉल्ट रूप से लागू नहीं करता है, लेकिन उन स्तंभों के लिए कौन से पंक्तियों के मानों का उपयोग किया जाता है, यह परिभाषित नहीं है। जबकि आपको वह मिल सकता है जो आप चाहते हैं, आप भी नहीं कर सकते। और अगर आप ऐसा करते हैं तो भी संभावना है कि यह भविष्य में बदल जाएगा।
आदेश सामान्य रूप से GROUP BY से स्वतंत्र होता है, हालाँकि यदि आप कोई ORDER खंड निर्दिष्ट नहीं करते हैं, तो परिणामों को इस आधार पर क्रमित किया जाएगा कि GROUPing करने के लिए क्या आवश्यक था (अर्थात, यदि यह पंक्तियों को एक क्रम में क्रमित करने में मदद करता है) GROUP BY तब तक MySQL बाद में रिकॉर्ड्स को फिर से व्यवस्थित करने की जहमत नहीं उठाएगा जब तक कि आप इसे विशेष रूप से ORDER BY क्लॉज के साथ नहीं बताते)।
तो आपके वर्तमान डेटा के साथ, ads_post_id के आधार पर समूहित करने पर लौटाई गई आईडी का मान 22, 23, 24, 104, 250, 253 या 767 हो सकता है। कौन सा MySQL उपयोग करना चाहता है, यह परिभाषित नहीं है।
आपके वर्तमान डेटा को ठीक करने के साथ यह मामूली है क्योंकि आप केवल MAX आईडी प्राप्त कर सकते हैं:-
SELECT ads_post_id, MAX(id)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
MAX प्रत्येक GROUPed मान के लिए 1 पंक्ति लौटाएगा।
सामान्य समस्या यह है कि लोग उस पंक्ति के लिए एक और कॉलम चाहते हैं। उदाहरण के लिए मान लें कि आपके नमूना डेटा की प्रत्येक पंक्ति का एक IP पता भी था, और आप वह चाहते थे जो ads_post_id के लिए उच्चतम आईडी के बराबर हो:-
id | ads_post_id ip_address
---------------------------------------------------------------------------
22 | 983314845117571 192.168.0.0
23 | 983314845117571 192.168.0.5
24 | 983314845117571 192.168.0.7
104 | 983314845117571 192.168.0.0
250 | 983314845117571 192.168.0.4
253 | 983314845117571 192.168.0.6
767 | 983314845117571 192.168.0.1
---------------------------------------------------------------------------
इस मामले में आप केवल MAX का उपयोग नहीं कर सकते। उदाहरण के लिए यदि आपने कोशिश की:-
SELECT ads_post_id, MAX(id), MAX(ip_address)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
आपको निम्न डेटा वापस मिल जाएगा
id | ads_post_id ip_address
---------------------------------------------------------------------------
767 | 983314845117571 192.168.0.7
---------------------------------------------------------------------------
यदि आपने SQL के अधिकांश फ्लेवर में निम्नलिखित को आजमाया है तो आपको एक त्रुटि मिलेगी। MySQL में डिफ़ॉल्ट सेटिंग्स के साथ आपको एक परिणाम मिलेगा, लेकिन कौन सा IP पता लौटाया गया है, यह परिभाषित नहीं है (और वास्तव में यादृच्छिक)।
SELECT ads_post_id, MAX(id), ip_address
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
इसका समाधान या तो उप क्वेरी में प्रत्येक ads_post_id के लिए अधिकतम आईडी प्राप्त करना और फिर शेष मान प्राप्त करने के लिए तालिका में वापस शामिल होना है:-
SELECT a.ads_post_id,
a.id,
a.ip_address
FROM fb_ads a
INNER JOIN
(
SELECT ads_post_id, MAX(id) AS max_id
FROM fb_ads
GROUP BY ads_post_id
) sub0
ON a.ads_post_id = sub0.ads_post_id
AND a.id = sub0.max_id
एक विकल्प है (ab) GROUP_CONCAT समुच्चय फ़ंक्शन का उपयोग करना। GROUP_CONCAT एक साथ संयोजित सभी मानों को 1 फ़ील्ड में वापस लाएगा, प्रत्येक को एक , (डिफ़ॉल्ट रूप से) से अलग किया जाएगा। आप उस क्रम को बाध्य करने के लिए एक ORDER BY खंड जोड़ सकते हैं जिसमें वे सम्मिलित हैं। सब कुछ पहले कॉमा तक वापस करने के लिए आप SUBSTRING_INDEX का उपयोग कर सकते हैं।
यह साधारण डेटा के लिए उपयोगी हो सकता है, लेकिन टेक्स्ट डेटा या फ़ील्ड के साथ समस्याग्रस्त हो जाता है जो अधिकतम NULL हो।
SELECT a.ads_post_id,
SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(ip_address ORDER BY id DESC), ',', 1)
FROM fb_ads
GROUP BY ads_post_id