Ich habe eine users
-Tabelle und eine payments
-Tabelle für jeden Benutzer, dessen Zahlungen Zahlungen haben. In der payments
-Tabelle können mehrere Zahlungen vorhanden sein. Ich möchte alle Benutzer auswählen, die Zahlungen haben, aber nur die letzte Zahlung auswählen. Ich versuche diese SQL, aber ich habe noch nie geschachtelte SQL-Anweisungen ausprobiert, also möchte ich wissen, was ich falsch mache. Schätzen Sie die Hilfe
SELECT u.*
FROM users AS u
INNER JOIN (
SELECT p.*
FROM payments AS p
ORDER BY date DESC
LIMIT 1 )
ON p.user_id = u.id
WHERE u.package = 1
Sie benötigen eine Unterabfrage, um das späteste Datum per user ID
zu erhalten.
SELECT a.*, c.*
FROM users a
INNER JOIN payments c
ON a.id = c.user_ID
INNER JOIN
(
SELECT user_ID, MAX(date) maxDate
FROM payments
GROUP BY user_ID
) b ON c.user_ID = b.user_ID AND
c.date = b.maxDate
WHERE a.package = 1
SELECT u.*, p.*, max(p.date)
FROM payments p
JOIN users u ON u.id=p.user_id AND u.package = 1
GROUP BY u.id
ORDER BY p.date DESC
Schauen Sie sich diese sqlfiddle
SELECT u.*, p.*
FROM users AS u
INNER JOIN payments AS p ON p.id = (
SELECT id
FROM payments AS p2
WHERE p2.user_id = u.id
ORDER BY date DESC
LIMIT 1
)
Diese Lösung ist besser als die akzeptierte Antwort , weil sie korrekt funktioniert, wenn Zahlungen mit demselben Benutzer und demselben Datum eingehen.
SELECT u.*
FROM users AS u
INNER JOIN (
SELECT p.*,
@num := if(@id = user_id, @num + 1, 1) as row_number,
@id := user_id as tmp
FROM payments AS p,
(SELECT @num := 0) x,
(SELECT @id := 0) y
ORDER BY p.user_id ASC, date DESC)
ON (p.user_id = u.id) and (p.row_number=1)
WHERE u.package = 1
Die Antwort von John Woo half mir, ein ähnliches Problem zu lösen. Ich habe seine Antwort verbessert, indem ich auch die richtige Reihenfolge einstelle. Das hat für mich funktioniert:
SELECT a.*, c.*
FROM users a
INNER JOIN payments c
ON a.id = c.user_ID
INNER JOIN (
SELECT user_ID, MAX(date) as maxDate FROM
(
SELECT user_ID, date
FROM payments
ORDER BY date DESC
) d
GROUP BY user_ID
) b ON c.user_ID = b.user_ID AND
c.date = b.maxDate
WHERE a.package = 1
Ich bin nicht sicher, wie effizient das ist.
Matei Mihai hat eine einfache und effiziente Lösung gegeben, die jedoch erst dann funktioniert, wenn Sie einen MAX(date)
in den SELECT-Teil einfügen. Diese Abfrage wird zu:
SELECT u.*, p.*, max(date)
FROM payments p
JOIN users u ON u.id=p.user_id AND u.package = 1
GROUP BY u.id
Und order by macht keinen Unterschied in der Gruppierung, aber es kann das von group zur Verfügung gestellte Endergebnis nach sortieren. Ich habe es versucht und es hat für mich funktioniert.
Es gibt zwei Probleme mit Ihrer Abfrage:
INNER JOIN (SELECT ...) AS p ON ...
benennen. Angenommen, es gibt keine Bindungen für payments.date
, versuchen Sie Folgendes:
SELECT u.*, p.*
FROM (
SELECT MAX(p.date) AS date, p.user_id
FROM payments AS p
GROUP BY p.user_id
) AS latestP
INNER JOIN users AS u ON latestP.user_id = u.id
INNER JOIN payments AS p ON p.user_id = u.id AND p.date = latestP.date
WHERE u.package = 1
Meine Antwort direkt von @valex inspiriert, sehr nützlich, wenn Sie mehrere Spalten in der ORDER BY-Klausel benötigen.
SELECT u.*
FROM users AS u
INNER JOIN (
SELECT p.*,
@num := if(@id = user_id, @num + 1, 1) as row_number,
@id := user_id as tmp
FROM (SELECT * FROM payments ORDER BY p.user_id ASC, date DESC) AS p,
(SELECT @num := 0) x,
(SELECT @id := 0) y
)
ON (p.user_id = u.id) and (p.row_number=1)
WHERE u.package = 1