Assuming that the ordering of the subqueries is supposed to be the same (not a typo), then the combination of the three is a greatest-n-per-group problem. MySQL has several existing solutions for this, and if the number of rows-per-group is small I think I prefer the style in this answer, which for your case would look like this:
SELECT rToUse.mr_id, rToUse.mesaj, rToUse.kayitZaman
FROM Mesajlarreply rToUse
LEFT JOIN Mesajlarreply rKnockout
ON rKnockout.cId = rToUse.cId AND rToUse.mr_id < rKnockout.mr_id
WHERE rKnockout.mr_id IS NULL
(This works because when the rows are joined, the one with the greatest mr_id
has no match. All other rows are then discarded due to rKnockout.mr_id IS NULL
being true)
The fact that you're using three subqueries is probably doing a number on the system.
Your CASE
statement evaluates to a simple set of Boolean conditions:
(M.k1 = '1' AND M.k2 = K.id) OR (M.k1 <> '1' AND M.k2 = '1' AND M.k1 = K.id)
... I'm going to assume that you don't have cases where both k1
and k2
equal '1'
at the same time, so the M.k1 <> '1'
(which was to preserve the semantics of the CASE
if that is true) would be unnecessary. Note that OR
s can still be a performance pain point. Too, if any of those columns are actually some numeric type, the joins will require conversion first, which will probably kill performance.
So, I'd probably start by writing the query about like this:
SELECT K.id, M.m_id, K.sil, K.banli, K.foto, K.kullaniciAdi, K.ad, K.soyad, K.gender,
R.mr_id, r.mesaj, r.kayitZaman
FROM Mesajlar M
JOIN Kullanicilar K
ON (M.k1 = '1' AND M.k2 = K.id)
OR (M.k2 = '1' AND M.k1 = K.id)
LEFT JOIN (SELECT rToUse.cId, rToUse.mr_id, rToUse.mesaj, rToUse.kayitZaman
FROM Mesajlarreply rToUse
LEFT JOIN Mesajlarreply rKnockout
ON rKnockout.cId = rToUse.cId
AND rToUse.mr_id < rKnockout.mr_id
WHERE rKnockout.mr_id IS NULL) R
ON R.cId = M.m_id
ORDER BY M.m_id DESC
LIMIT 20
(Untested, of course - no provided dataset)
I've used a LEFT JOIN
for the subquery to preserve the given data semantics. If you have rows for all cases (or only care about those who do), it could be changed to an (INNER) JOIN
. Depending on how your dataset is laid out (and what indices you have/don't have), this may not perform any better, but this should generally be friendlier to the optimizer.