2016-02-24 19 views
5

Bu oldukça yaygın bir durumdur, ancak yanlış bir şey yapıyorum emin değilim.Son veri grubu-bir alt sorgu olmadan

TABLE POSTS [ ID, USER_ID, TOPIC_ID, TIME ] 

Ben topic_id '1'

SELECT p.* 
FROM 
    posts p, 
    (
    SELECT user_id, max(time) mtime 
    FROM  posts 
    WHERE topic_id = 1 
    GROUP BY user_id 
) pm 
WHERE 
    p.user_id = pm.user_id AND 
    p.time = pm.mtime 

Bu doğru üzerinde her kullanıcı tarafından sadece son yazılan almak istiyorum? Alt sorgu olmadan bunu yapmanın bir yolu var mı?

Bu veriyi bahar veri sorgularıyla almanın bir yolu var mı, yoksa bu sadece bir JDBC/saklı yordam mı?

+3

Bu doğrudur - ancak her zaman açık JOIN sözdizimini kullanın – Strawberry

+1

Ah, çok erken konuştum. Subquery'nin SELECT'ine user_id eklemeniz gerekir ve en iyi uygulama, GROUP BY'de topic_id'in dahil edilmesi gerektiğini belirtir (bu durumda kesinlikle gerekli olmasa da) – Strawberry

+0

Evet, çeviriyi alanımdan "gönderiler" e gönderdim bir bit, "topic_id" yerine "SELECT user_id, max (time)" olmalıdır - Düzenlenen – qzshard

cevap

1

Katılabilirsiniz kullanarak bir alt sorgu kullanarak olmadan her kullanıcı için en son yazı alabilirsiniz:

SELECT p.* 
FROM posts p 
LEFT OUTER JOIN posts t 
ON(p.user_id = t.user_id and p.time < t.time and t.topic_id = 1) 
WHERE p.topic_id = 1 and t.topic_id is null 
+0

Oldukça ilginç, ben ' Bu "hile" henüz görmedim. Ancak, herhangi bir konudaki son gönderiyi '1' konusu değil, tüm kullanıcılar tarafından alır - sonuçları filtrelemek için bir yol var mı? – qzshard

+0

@qzshard Evet, elbette, ON yan tümcesi içinde, cevabı güncelledi .. Eğer yardımcı olsaydı size yardımcı olurum (^) ve onay (V) – sagi

+0

Eski okul. İyi, ama bu yöntemin iyi durumda olmadığını not edin (OP'nin kendi çözümünün aksine) – Strawberry

0

Alt sorgu olmadan yapmak için HAVING'u kullanın.

SELECT user_id, topic_id, time 
FROM  posts 
WHERE topic_id = 1 
GROUP BY user_id 
HAVING time = max(time) 
+0

'HAVING time = ..' 'Mysql'de bu izin verilir –

+0

Denemedim ama şu şekilde düşünün: https: //dev.mysql.com/doc/refman/5.0/en/group-by-handling.html – user1717259

+0

çalışmıyor, tek satırlık bir bağlamda "sahip olma" koşulunu kullanamazsınız – qzshard

1

burada sub-query önlemek için nasıl emin değil miyim ama bunu yapmanın başka bir yolu

olacak
SELECT p.* 
FROM posts p 
WHERE p.time = (SELECT Max(time) mtime 
       FROM posts pm 
       WHERE pm.topic_id = 1 
         AND p.user_id = pm.user_id) 

Pencere Fonksiyonu Row_number tür durumlarda maalesefçok yardımcı olacak

+0

teşekkürler, bu başka sorularda gördüğüm başka bir yoldur. Fakat performans açısından, bu çok yoğun bir sorgu değil (orjinaline kıyasla)? – qzshard

+0

@ qzshard- bunu gerçek zamanlı verilerinizle test edebilirsiniz –

0

'u desteklemiyor Bir alt sorgudan kaçınan bir başka çözüm (ancak yine de o kadar hızlı olmayabilir), substring_index'i en sonuncudan istediğiniz her alan için azalan zamana göre sıralamak ve sonra ilk girdiyi almak için SUBSTRING_INDEX kullanarak SUBSTRING_INDEX tarafından döndürüldü.

SELECT user_id, 
    SUBSTRING_INDEX(GROUP_CONCAT(`id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`topic_id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`time` ORDER BY `time` DESC), ',', 1) 
FROM posts 
WHERE topic_id = 1 
GROUP BY user_id