2011-01-25 7 views
19

मैंने सहायता के लिए साइट की खोज की है लेकिन अभी भी संघर्ष कर रहा है। यहां मेरी तालिका है:तालिका (डेटाटाइम फ़ील्ड) में नवीनतम रिकॉर्ड का चयन करें

 
messages 
======== 
id 
thread_id 
user_id 
subject 
body 
date_sent 

असल में मैं प्रत्येक थ्रेड_आईडी के लिए नवीनतम रिकॉर्ड पुनर्प्राप्त करना चाहता हूं। मैंने निम्नलिखित कोशिश की है:

SELECT id, thread_id, user_id, subject, body, date_sent 
FROM messages 
WHERE user_id=1 AND date_sent=(select max(date_sent)) 
GROUP BY thread_id 
ORDER BY date_sent DESC 

लेकिन यह मुझे सबसे पुराना रिकॉर्ड दे रहा है, न कि नवीनतम!

कोई भी सलाह देने में सक्षम है?

संपादित करें: टेबल डंप:

 
-- 
-- Table structure for table `messages` 
-- 

CREATE TABLE IF NOT EXISTS `messages` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `thread_id` int(10) unsigned NOT NULL, 
    `user_id` int(10) unsigned NOT NULL, 
    `body` text NOT NULL, 
    `date_sent` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ; 

-- 
-- Dumping data for table `messages` 
-- 

INSERT INTO `messages` (`id`, `thread_id`, `user_id`, `body`, `date_sent`) VALUES 
(1, 1, 1, 'Test Message', '2011-01-20 00:13:51'), 
(2, 1, 6, 'Test Message', '2011-01-20 01:03:50'), 
(3, 1, 6, 'Test Message', '2011-01-20 01:22:52'), 
(4, 1, 6, 'Test Message', '2011-01-20 11:59:01'), 
(5, 1, 1, 'Test Message', '2011-01-20 11:59:22'), 
(6, 1, 6, 'Test Message', '2011-01-20 12:10:37'), 
(7, 1, 1, 'Test Message', '2011-01-20 12:10:51'), 
(8, 2, 6, 'Test Message', '2011-01-20 12:45:29'), 
(9, 1, 6, 'Test Message', '2011-01-20 13:08:42'), 
(10, 1, 1, 'Test Message', '2011-01-20 13:09:49'), 
(11, 2, 1, 'Test Message', '2011-01-20 13:10:17'), 
(12, 3, 1, 'Test Message', '2011-01-20 13:11:09'), 
(13, 1, 1, 'Test Message', '2011-01-21 02:31:43'), 
(14, 2, 1, 'Test Message', '2011-01-21 02:31:52'), 
(15, 4, 1, 'Test Message', '2011-01-21 02:31:57'), 
(16, 3, 1, 'Test Message', '2011-01-21 02:32:10'), 
(17, 4, 6, 'Test Message', '2011-01-20 22:36:57'), 
(20, 1, 6, 'Test Message', '2011-01-20 23:02:36'), 
(21, 4, 1, 'Test Message', '2011-01-20 23:17:22'); 

संपादित करें: क्षमा याचना - मैं चीजों को थोड़ा उलझन में यहाँ मिल गया है सकते हैं - मूल रूप से मैं क्या चाहते हैं, किसी दिए गए user_id के लिए सभी संदेशों को पुनः प्राप्त करने के फिर नवीनतम संदेश नहीं मिल रहा है (प्रति thread_id) उन पुनर्प्राप्त संदेशों से।

+0

यह सॉर्ट क्रम यही समस्या है या इसके लिए सबसे पुराने रिकॉर्ड को चुन रही है है नवीनतम उपयोगकर्ता की बजाय प्रत्येक उपयोगकर्ता? – ChrisF

+0

यह नवीनतम के बजाय सबसे पुराना रिकॉर्ड चुन रहा है। ऑर्डर द्वारा ठीक काम कर रहा है। – GSTAR

+0

क्या आप कुछ prefilled मूल्यों के साथ तालिका में एक डंप प्रदान करने में सक्षम होंगे ताकि मैं इस पर अपनी क्वेरी का परीक्षण कर सकूं। मुझे लगता है कि मेरे पास स्केलर सबक्वायरी का उपयोग करके बहुत आसान तरीका है और सभी समूह बाई क्रॉस जॉइन इत्यादि का उपयोग नहीं कर रहा है। – andrew

उत्तर

33
SELECT id, thread_id, user_id, subject, body, date_sent 
    FROM messages WHERE date_sent IN (
    SELECT MAX(date_sent) 
     FROM messages WHERE user_id =6 GROUP BY thread_id 
) 
    ORDER BY thread_id ASC , date_sent DESC; 

मुझे पता है अगर यह अब काम करता है

+0

धन्यवाद मालिक, यह सही है। अगर सभी ठीक है तो परीक्षण करना जारी रखेगा और आपका जवाब स्वीकार करेगा। – GSTAR

+0

धन्यवाद, मेरे लिए भी काम किया! – Alyas

+0

उस क्वेरी के साथ बहुत सी चीजें गलत हैं लेकिन बग्स कपटपूर्ण होंगे और आपको तब तक नहीं मिलेगा जब तक कि बहुत सारे डेटा न हों। मैं अपना जवाब लिखने की कोशिश करूंगा। – PaulC

4

यह दो स्टॉप प्रक्रिया है। सबसे पहले प्रत्येक thread_id के लिए नवीनतम तिथियां पाएं। फिर रिकॉर्ड इन तारीखों और मिलान thread_id रों

SELECT t.id, t.thread_id, t.user_id, t.body, t.date_sent 
FROM messages AS t 
CROSS JOIN (
    SELECT thread_id, MAX(date_sent) AS date_sent FROM messages WHERE user_id = 1 GROUP BY thread_id 
) AS sq 
USING (thread_id, date_sent) 

ध्यान दें कि दो (या अधिक) messages अगर एक ही date_sent और एक ही thread_id वे दोनों का चयन किया जाएगा (क्योंकि आपको बता नहीं सकता जो एक नया है) है कि चयन

+0

यह सब सच है। इस ऑपरेशन को अक्सर "समूहवार अधिकतम" कहा जाता है। और भी उदाहरणों के लिए, इसे पढ़ें: http://jan.kneschke.de/projects/mysql/groupwise-max/ ... या "groupwise max" के लिए Google। – TehShrike

+0

इसके लिए धन्यवाद। क्या आप एक उदाहरण प्रदान कर सकते हैं जो मैंने उपयोग किए गए समान वाक्यविन्यास का उपयोग किया है, यानी क्रॉस जॉइन और उपयोग किए बिना? मुझे पता है कि आपकी विधि शायद अधिक प्रभावी है, लेकिन मैं सरल sytnax का उपयोग करना पसंद करता हूं जिसका उपयोग मैं कर रहा हूं :) – GSTAR

+0

कुछ पूर्वनिर्धारित मानों के साथ आप तालिका का एक डंप प्रदान करें और मुझे लगता है कि मैं आपको एक स्केलर सबक्वायरी का उपयोग करने के लिए एक बहुत ही सरल क्वेरी लिख सकता हूं। और यह क्रॉस जॉइन या ग्रुप बाई – andrew

1

जो मैं देख सकता हूं, आपकी समस्या उप-क्वेरी के साथ है। उप-क्वेरी वास्तव में मौजूदा रिकॉर्ड से अधिकतम दिनांक_सेंट फ़ील्ड निकालने जा रही है, दूसरे शब्दों में, क्योंकि बाह्य क्वेरी तालिका में एक रिकॉर्ड को एक बार ट्रैक करता है जब उप-क्वेरी "date_sent=(select max(date_sent)" में दो दिनांक_सेंट फ़ील्ड हमेशा एक ही होंगी । किसी विशेष थ्रेड_आईडी के लिए पहला रिकॉर्ड प्रदर्शित करने के बाद, यह थ्रेड_आईडी के द्वारा समूहबद्ध होने के बाद उस थ्रेड_आईडी के लिए कोई अन्य रिकॉर्ड नहीं दिखाता है। यही कारण है कि, यह हमेशा प्रत्येक thread_id के लिए दर्ज पहला रिकॉर्ड दिखाएगा। बीटीडब्ल्यू, यह प्रत्येक थ्रेड_आईडी के लिए दर्ज पहला रिकॉर्ड दिखा रहा है और जल्द से जल्द दिनांक_सेंट रिकॉर्ड नहीं है। आपका परिणाम आपकी तालिका में रिकॉर्ड के स्थान पर निर्भर है और date_sent के मान पर नहीं है। यकीन है कि अगर ऐसा नहीं है कि मैं इस समझाया सही ढंग से है, लेकिन वैसे भी, आपकी समस्या को ठीक करने के लिए कोशिश:

SELECT id, thread_id, user_id, subject, body, date_sent 
FROM messages 
WHERE user_id=1 AND date_sent IN (select max(date_sent) from messages GROUP BY thread_id) 
GROUP BY thread_id 
ORDER BY date_sent DESC; 

सबसे पहले, उप क्वेरी पूरे से thread_id प्रति अधिकतम दिनांकों ऊपर खींचने के लिए एक FROM खंड और एक GROUP BY खंड होना आवश्यक है टेबल और न केवल वर्तमान रिकॉर्ड। इसके अलावा, = को IN के साथ प्रतिस्थापित किया जाना चाहिए क्योंकि उप-क्वेरी के परिणामस्वरूप कई रिकॉर्ड हो सकते हैं। यदि तालिका में उसी तारीख पर एक ही थ्रेड-आईडी के दो रिकॉर्ड होते हैं, तो केवल पहला प्रदर्शित किया जाएगा। यह बाहरी क्वेरी में दूसरे GROUP BY खंड के कारण होता है। उस दिन कि thread_id के लिए सभी रिकॉर्ड प्रदर्शित करने के लिए प्रयास करें:

SELECT id, thread_id, user_id, subject, body, date_sent 
FROM messages 
WHERE user_id =1 AND date_sent IN (SELECT MAX(date_sent) FROM messages GROUP BY thread_id) 
ORDER BY thread_id ASC , date_sent DESC; 

दूसरा GROUP BY खंड को दूर करने और एक ORDER BY खंड जोड़कर, आप प्रत्येक thread_id के लिए है कि अधिकतम तारीख के लिए सभी संदेशों को दिखा सकते हैं और अभी भी थ्रेड दिखाने सही क्रम में। उम्मीद है की वो मदद करदे।

+0

हाय दोस्त, इसके लिए धन्यवाद। मैंने आपके दोनों प्रश्नों की कोशिश की, लेकिन प्रत्येक बार जब यह किसी दिए गए user_id के लिए रिकॉर्ड्स की सही संख्या नहीं लौटा रहा है। मेरे डेटासेट में कोई डुप्लिकेट तिथियां नहीं हैं। – GSTAR

+0

असल में ऐसा लगता है कि कुछ थ्रेड_आईडी को अनदेखा कर रहा है। – GSTAR

+0

ठीक है, मुझे यहां कुछ चीजें उलझन में मिल सकती हैं - मूल रूप से जो मैं चाहता हूं वह किसी दिए गए उपयोगकर्ता_आईडी के लिए सभी संदेशों को पुनर्प्राप्त करना है, फिर उन पुनर्प्राप्त संदेशों से नवीनतम संदेश (प्रति थ्रेड_आईडी) ढूंढें। – GSTAR

1

यह एक बहुत पुराना सवाल है, लेकिन वैसे भी करते हैं ...

आपका जहां खंड पर्याप्त विशिष्ट नहीं है, और सही रिकॉर्ड का चयन करने के लिए date_sent का उपयोग करना गलत है। इस प्रयास करें:

SELECT id, thread_id, user_id, subject, body, date_sent 
FROM messages 
WHERE id=(
    select m2.id from messages m2 
    where messages.thread_id=m2.thread_id 
    order by date_sent desc limit 1) 
ORDER BY date_sent DESC 

आपको लगता है कि आईडी हमेशा समय के साथ बढ़ जाती है ग्रहण करने के लिए चाहते हैं, यह शायद बेहतर प्रदर्शन करेंगे:

SELECT id, thread_id, user_id, subject, body, date_sent 
FROM messages 
WHERE id in (
    select max(m2.id) from messages m2 group by m2.thread_id) 
ORDER BY date_sent DESC 
संबंधित मुद्दे