Prenons le cas de deux tables: tbl_product
et tbl_transaction
.tbl_product
répertorie les détails du produit, y compris les noms et identifiants, tandis que tbl_transaction
répertorie les transactions impliquant les produits et inclut les dates, identifiants du produit, clients, etc.
Je dois afficher une page Web présentant 10 produits et pour chaque produit, les 5 dernières transactions. Jusqu'ici, aucune requête LEFT JOIN
ne semble fonctionner et la sous-requête ci-dessous aurait fonctionné si mysql pouvait autoriser la partie tx.product_id=ta.product_id
(échoue avec La colonne inconnue 'ta.product_id' dans 'clause Where': [ERROR: 1054] ).
SELECT
ta.product_id,
ta.product_name,
tb.transaction_date
FROM tbl_product ta
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx WHERE tx.product_id=ta.product_id LIMIT 5) tb
LIMIT 10
Existe-t-il un moyen de réaliser la liste dont j'ai besoin sans utiliser plusieurs requêtes dans une boucle ?
Modifier:
C’est exactement ce dont j'ai besoin de MySQL:
SELECT ta.product_id, ta.product_name, tb.transaction_date ...
FROM tbl_product ta
LEFT JOIN tbl_transaction tb ON (tb.product_id=ta.product_id LIMIT 5)
LIMIT 10
Bien sûr, c'est illégal, mais j'aimerais vraiment que ce ne soit pas le cas!
C’est là que les fonctions de classement seraient très utiles. Malheureusement, MySQL ne les prend pas encore en charge. Au lieu de cela, vous pouvez essayer quelque chose comme ce qui suit.
Select ta.product_id, ta.product_name
, tb.transaction_date
From tbl_product As ta
Left Join (
Select tx1.product_id, tx1.transaction_id, tx1.transaction_date
, (Select Count(*)
From tbl_transaction As tx2
Where tx2.product_id = tx1.product_id
And tx2.transaction_id < tx1.transaction_id) As [Rank]
From tbl_transaction As tx1
) as tb
On tb.product_id = ta.product_id
And tb.[rank] <= 4
Limit 10
Elle échoue car lorsque vous mettez des parenthèses autour de votre requête et lui donnez le pseudonyme "tb", vous avez créé une table dérivée. Votre table dérivée ne connaît pas la table tbl_product ayant le pseudonyme "ta"
Essayez d’utiliser ON ou WHERE en dehors de la table dérivée, puis référencez cette table en utilisant l’alias "tb" que vous avez fourni.
MODIFIER:
L'utilisation de "LIMIT" limite les résultats de la requête dans son intégralité. Alors que vous avez "LIMIT 10", vous voulez réellement 50 lignes (ou moins s'il y a moins de 5 historiques), est-ce exact? ?
10 produits, joints à 5 enregistrements historiques, renvoyant un total de 50 lignes.
Dans ce cas, vous pouvez avoir une solution de requête unique reliant la table de produit à elle-même dans une table dérivée ayant "LIMIT 10".
Tel que:
SELECT *
FROM tbl_product ta
JOIN (SELECT * FROM tbl_product tz WHERE tz.product_id = ta.product_id LIMIT 10) tc
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx
WHERE tx.product_id=ta.product_id LIMIT 5) tb
Vous pouvez également nous "entrer" et spécifier le top 10 tel que:
SELECT *
FROM tbl_product ta
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx
WHERE tx.product_id=ta.product_id LIMIT 5) tb
WHERE ta.product_id IN
(SELECT z.product_id FROM tbl_product z LIMIT 10)
Modifier:
Si vous souhaitez imposer une limite à chaque produit, je le séparerai en deux requêtes.
Commencez par obtenir une liste de 10 produits, puis lancez une autre requête pour chacun de ceux qui renvoient les cinq dernières transactions.
J'ai trouvé moyen de faire LEFT JOIN avec sous-requête, triés et limités, ses travaux sur RDS Amazon, MariaDB v10.2
LEFT JOIN activities last_activity ON last_activity.id = (
SELECT id FROM activities
WHERE contester_id = contesters.id AND `type` IN ({$last_activity_types})
ORDER BY id DESC LIMIT 1
)
Toutes les autres façons de faire LEFT JOIN avec GROUPING et SORTING ne fonctionnaient pas pour moi. Cet exemple est une exception qui fonctionne.