Bonjour,
Je suis fasse un problème que je n'arrive pas à resoudre. C'est une jointure entre trois tables. Je ne suis même pas sur que la troisième doit être jointe.
Entre Items et Users c'est assez simple. (J'utilise laravel 5.2)
left join `Item_Favoris` on `Item_Favoris`.`item_id` = `items`.`id`
Maintenant arrive la troisième table Item_Favoris. Cette table permet de mettre en favoris les Items par utilisateur.
Elles possèdes les champs id, item_id et user_id.
Ce que j'aimerais c'est : Si dans la table Item_Favoris il existe une entrée, ajouter is_favoris: 1 dans le resultat de la liste d'article. Autrement is_favoris: 0
{
"data":
[
{
"id": 1,
"user_id": 1,
"username": "Louis",
"brand": "Zara",
"size": 16,
"price": "50",
"is_favoris": 1
},
{
"id": 2,
"user_id": 1,
"username": "Louis",
"brand": "Adidas",
"size": 23,
"price": "16",
"is_favoris": 0
}
]
}
J'obtiens un peu de tout car j'ai tout essayé (left join, CASE WHEN, whereIn, etc.).
Je ne sais pas comment fonction laravel mais pour faire une jointure moi je fait ça pour mon forum
SELECT
f_topics.id AS topicsid,
f_topics.f_topic_content,
f_topics.f_topic_name,
f_topics.f_forum_id,
f_topics.f_user_id,
f_topics.f_topic_date,
f_topics.f_topic_vu,
f_topics.f_rep_topic_nb,
f_topics.f_autor_topic,
f_topics_reponse.f_topic_rep_date,
f_topics_reponse.id AS idrep,
f_topics_reponse.user_rep,
f_message_view.last,
f_message_view.user_id,
users.id AS usersid,
users.username,
CASE
WHEN f_topics.f_topic_date > f_topics_reponse.f_topic_rep_date THEN f_topics.f_topic_date
ELSE f_topics_reponse.f_topic_rep_date
END AS Lastdate
FROM f_topics
LEFT JOIN users ON users.id = f_topics.f_user_id
LEFT JOIN f_topics_reponse ON f_topics_reponse.f_topic_id = f_topics.id
LEFT JOIN f_message_view ON f_message_view.topic_id = f_topics.id AND f_message_view.user_id = ?
WHERE f_topics.f_forum_id = ?
GROUP BY f_topics.id
ORDER BY Lastdate DESC
Tu pourra y remarquer le GROUP BY
cette requete me retourne les topic par forum avec un ORDER BY Lastdate
que je fait avec le CASE
ensuite je regroupe tout avec l'id du topic.
Ne connaissant pas l'ORM de Laravel, je te donne une piste.
Faire une jointure classique avec tes 2 ID (items/favoris) sur la table "Item_Favoris" ainsi qu'un "GROUP BY Items.id" (pour éviter d'avoir plusieurs lignes pour le même item).
Ensuite, pour avoir ton "is_favoris", il ne te reste plus qu'à vérifier si c'est null : Item_Favoris.id IS NULL as is_favoris
Si c'est NULL, c'est qu'il n'y a aucun favoris, et inversement.
Salut, je ferais comme @Kenor également
Juste un conseil, lorsque tu poses un problème sur un forum met le en SQL, car le mettre avec un ORM spécifique peu faire "fuire" des personnes qui auraient pu t'aider..
Egalement, j'espère que tu maîtrises bien SQL avant de passer par un ORM, petit conseil pratique : faire les requêtes en SQL puis après utiliser l'orm (pour les queries plus compliquées)
Merci à tous pour vos réponses.
On peut utiliser SQL à 100% en brut avec laravel si on veut. Donc c'était juste une précision mais dans l'absolue ma question est sur SQL.
@Emix Je viens d'editer en SQL. Tu as raison.
Il est vrai que je ne maitrise pas parfaitement le SQL mais l'utilisation d'un ORM ne s'arrête pas là, j'aurais eu le même problème sans ORM de mon point de vue.
@neecride @Kenor Merci aux deux, quand je fais le GROUP BY items.id
ça regroupe mais pas dans le bon ordre. Donc j'ajoute le ORDERY BY is_favoris
qui ne fait pas son boulot.
Si j'enlève le GROUP BY items.id
on remarque que l'order by marche.
{
"data":[
{
"id": 1,
"user_id": 1,
"brand": "Zara",
"size": 16,
"price": "50",
"name": "Louis",
"is_favoris": 1,
},
{
"id": 1,
"user_id": 1,
"brand": "Zara",
"size": 16,
"price": "50",
"name": "Louis",
"is_favoris": 0,
}
]
}
Mais si je le remets
{
"data":[
{
"id": 1,
"user_id": 1,
"brand": "Zara",
"size": 16,
"price": "50",
"name": "Louis",
"is_favoris": 0,
}
]
}
Une idée pourqoi ?
Voici toute la requête :
select items.id, items.user_id, items.photos, items.brand, items.size, items.price, users.name, users.avatar, users.canton, CASE WHEN favoris.user_id = ? THEN 1 ELSE 0 END AS is_favoris from items left join users on users.id = items.user_id left join item_favoris on item_favoris.item_id = items.id where (items.status = ? and items.photos != ?) and items.id not in (select solds.id from solds) group by items.id order by is_favoris desc, ascended_at desc
Je vais répondre moi même à la dernière question. Il faut ajouter MAX() à CASE WHEN comme ceci :
max(CASE WHEN favoris.user_id = ? THEN 1 ELSE 0 END) AS is_favoris
et le groupby et le orderby deviennent inutiles.
Pourquoi ça ne marchait pas ? Simplement parce que groupby est fait avant le orderby.