2012-11-19 13 views
13

तालिका:php mysql समूह के आधार पर नवीनतम रिकॉर्ड, नहीं पहले रिकॉर्ड प्राप्त करने के लिए

(`post_id`, `forum_id`, `topic_id`, `post_time`) 
(79, 8, 4, '2012-11-19 06:58:08'); 
(80, 3, 3, '2012-11-19 06:58:42'), 
(81, 9, 9, '2012-11-19 06:59:04'), 
(82, 11, 6, '2012-11-19 16:05:39'), 
(83, 9, 9, '2012-11-19 16:07:46'), 
(84, 9, 11, '2012-11-19 16:09:33'), 

क्वेरी:

SELECT post_id, forum_id, topic_id FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC 
LIMIT 5 

परिणाम:

[0] => [post_id] => 84 [forum_id] => 9 [topic_id] => 11 
[1] => [post_id] => 82 [forum_id] => 11 [topic_id] => 6 
[2] => [post_id] => 81 [forum_id] => 9 [topic_id] => 9 
[3] => [post_id] => 80 [forum_id] => 3 [topic_id] => 3 
[4] => [post_id] => 79 [forum_id] => 8 [topic_id] => 4 

समस्या:

क्वेरी को फिर से लिखने के लिए कैसे करें ताकि मैं t post_id -> 83 post_id के बजाय 83>> 81 देता है?

वे दोनों एक ही मंच और विषय आईडी है, लेकिन post_id -> 81 post_id से एक पुराने तिथि है -> 83

लेकिन यह है कि समूह के आधार पर 'पहली' रिकॉर्ड और नहीं 'नवीनतम हो जाता है लगता है ' एक।

मैं

SELECT post_id, forum_id, topic_id, MAX(post_time) 

करने के लिए क्वेरी को बदलने की कोशिश की, लेकिन वह दोनों POST_ID 81 और 83

उत्तर

24

यदि आप समूह क्लॉज में उपयोग नहीं किए गए गुणों का चयन करते हैं, और समेकित नहीं होते हैं, तो परिणाम अनिर्दिष्ट है। आईई आप नहीं जानते कि अन्य विशेषताओं से कौन सी पंक्तियां चुनी गई हैं। (एसक्यूएल मानक ऐसे प्रश्नों की अनुमति नहीं देता है, लेकिन MySQL अधिक आराम से है)।

क्वेरी तब लिखी जानी चाहिए के रूप में

SELECT post_id, forum_id, topic_id 
FROM posts p 
WHERE post_time = 
    (SELECT max(post_time) FROM posts p2 
    WHERE p2.topic_id = p.topic_id 
    AND p2.forum_id = p.forum_id) 
GROUP BY forum_id, topic_id, post_id 
ORDER BY post_time DESC 
LIMIT 5; 

या

SELECT post_id, forum_id, topic_id FROM posts 
NATURAL JOIN 
(SELECT forum_id, topic_id, max(post_time) AS post_time 
FROM posts 
GROUP BY forum_id, topic_id) p 
ORDER BY post_time 
LIMIT 5; 
+0

स्पष्टीकरण और कोड के लिए धन्यवाद। दोनों प्रश्न काम किया। – shanebp

+0

मैंने आपको पहली बार क्वेरी का उपयोग किया था, लेकिन यह बदलने से पहले काम नहीं करता है ... जहां पोस्ट_टाइम = ... से ... जहां पोस्ट_टाइम ... जहां मुझे एक परिणाम मिला है। –

+0

यह इतनी परेशानी क्यों है? एसक्यूएल का उपयोग करके यह [तालिका] से [चयन] ग्रुप [कॉलम] 'से चुनें, जो सबसे पुराने के बजाय नवीनतम का चयन करता है, तार्किक अधिकार लगता है? –

10

यह बहुत ही सुंदर नहीं है, लेकिन यह काम करता है देता है:

SELECT * FROM (SELECT post_id, forum_id, topic_id FROM posts 
ORDER BY post_time DESC) as temp 
GROUP BY topic_id 
+0

यह डुप्लिकेट निकाल देता है लेकिन परिणाम यह काम किया जाता विषय आईडी एएससी – shanebp

+2

आपकी क्वेरी के लिए इस जोड़ने के क्रम में हैं: द्वारा post_time DESC सीमा 5 – shanebp

5

की तरह कुछ कोशिश
SELECT post_id, forum_id, topic_id 
FROM (SELECT post_id, forum_id, topic_id 
     FROM posts 
     ORDER BY post_time DESC) 
GROUP BY topic_id 
ORDER BY topic_id desc 
LIMIT 0,5 

order by और limit को आवश्यकतानुसार बदलें।

+0

परिणाम एक खाली सरणी है आदेश। – shanebp

+0

मैंने थोड़ा सा प्रश्न संपादित किया। मुझे समझ में नहीं आता कि यह क्यों काम नहीं करेगा। मैंने कोशिश नहीं की, लेकिन यह एक आम तकनीक है। घोंसले के सवाल है कि। यह मानते हुए कि आंतरिक क्वेरी सही परिणाम देता है, बाहरी क्वेरी को इसका परिणाम देना चाहिए। – NappingRabbit

+0

अगर आप डीबग करना चाहते हैं, तो पहले आंतरिक क्वेरी चलाएं। – NappingRabbit

0

शायद नहीं कर का सबसे अच्छा तरीका है लेकिन कभी कभी समारोह group_concat() userfull हो सकता है, यह हल कर की तरह आप चाहते हैं सभी एकत्रित मूल्यों की एक स्ट्रिंग वापस आ जाएगी और अल्पविराम से अलग (युग्मित मूल्य अंतरिक्ष से अलग होते हैं)। मैं स्ट्रिंग में पहली आईडी को काटने के लिए फ़ंक्शन SPLIT_STRING() का उपयोग करता हूं।

SELECT 
post_id, 
SPLIT_STRING(group_concat(forum_id, post_time ORDER BY post_time DESC) ,' ',1)as forum_id, 
SPLIT_STRING(group_concat(topic_id, post_time ORDER BY post_time DESC) ,' ',1)as topic_id , 
FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC 
LIMIT 5 

तो एकत्रित forum_id, post_time इस तरह होगा:

81 2012-11-19 06: 59: 04,83 2012-11-19 16:07:46

तो तुम पूर्णांकों और datetime जोड़ों के एक स्ट्रिंग प्रतिनिधित्व के साथ काम करने की जरूरत है, प्रत्येक जोड़ों अल्पविराम के द्वारा अलग तो मैं इस समारोह पहले INT पाने के लिए इस्तेमाल किया:

CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT) 
RETURNS VARCHAR(255) 
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos), 
     LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1), 
     delim, ''); 

नोट: फ़ंक्शन SPLIT_STRING (str, delim, pos) यहां पाया गया: Equivalent of explode() to work with strings in MySQL

0

यह आपके लिए भी ठीक काम करेगा।

SELECT * 
FROM (
    SELECT post_id, forum_id, topic_id FROM posts 
    ORDER BY post_time DESC 
    LIMIT 5 
) customeTable 
GROUP BY topic_id 
संबंधित मुद्दे