Bonjour,

Voila je rencontre un soucis avec une requête. Sur l'accueil d'un site vitrine, je souhaite afficher les 4 derniers éléments publiés, peu importe leur type (article, event, galerie...).
Pour l'instant je n'affiche que les 4 derniers articles actifs, classés par date.
Mais j'aimerai aussi afficher dans ce jeu de résultat, des événements, et des galeries photos publiées sur le site, toujours par jeu de 4, et toujours classés par date de publication.

Le problème c'est que ces tables là n'ont aucun lien entre elles. Ce sont des entités complètement différentes, et le nom de leur colonnes est différent. En sachant, que je ne dois récupérer que les lignes qui ont leur colonne statut "actif", que je ne dois récupérer que 4 résultats à chaque fois, et que ces resultats doivent etre classés par date de publication, peu importe de quelle table ils proviennent. Un vrai casse tete.

Ce que je fais

Pour l'instant, toutes les tentatives que j'ai fait, me mélangent les lignes de résultats entre elles.
C-a-d que sur la première ligne du tableau de résultat, ça me mélange un article et un event au lieu de séparer les résultats.

voici la requête avec laquelle je récupère les 4 derniers articles actifs :

SELECT * FROM `articles` WHERE `a_date_publi` <= NOW() AND `a_actif`=1 ORDER BY `a_date_publi`  DESC LIMIT 0,4

Ce que je veux

Pouvoir récupérer dans le même jeu de 4 résultats, des events si leur date correspond aux 4 derniers éléments rentrés.

Ce que j'obtiens

Toutes les requêtes de JOIN (http://sql.sh/2401-sql-join-infographie) demandent une équivalence dans la table voisine, hors je n'ai aucun joint entre ces tables, et je ne comprends pas comment je peux "mixer" les résultats directement dans la requête. Je me demande si je vais pas faire 3 requêtes, et mixer les tableaux en PHP en fonction des dates...

11 réponses


Huggy
Réponse acceptée

Tu pourrais faire une requête Union de plusieurs requêtes puis en extraire que 4 lignes

SELECT * FROM (
    SELECT nomarticle AS chptexte, datecreate AS chpdate FROM articles WHERE a_actif='1'
    UNION
    SELECT nomevent AS chptexte, datecreateevent AS chpdate FROM events WHERE a_actif='1'
) AS requnion ORDER BY chpdate LIMIT 4

tu as regardé du coté des sous-requetes ? :)

http://sql.sh/cours/sous-requete

RiderFx3
Auteur

Bonjour et merci pour ta réponse, oui j'avais déjà regardé, mais je ne comprends pas comment je peux l'articuler étant donné que je cherche à regrouper les résultats de plusieurs tables, et non pas isoler le résultat d'une table en fonction d'une autre.

En gros, il faudrait que je mélange complètement les deux tables, puis que je fasse une requête avec la date en condition pour ne récup que les 4 derniers en fonction de la date, indépendament du type d'élément que c'est. Le problème c'est que j'ai pas du tout pensé ma base comme ça quand je l'ai créé, et donc les colonnes n'ont rien à voir, et n'ont aucun lien entre elles.

RiderFx3
Auteur

Je veux dire par là que la requête peut très bien me retourner uniquement 4 articles, ou uniquement 4 events, ou un mix des deux, en fonction des dates. Désolé c'est difficile à expliquer.

RiderFx3
Auteur

Merci Huggy je pense qu'on s'approche de la solution avec ça, seulement même en simplifiant la requête au maximum, j'ai une erreur PhpMyAdmin.

SELECT * FROM `articles` WHERE `a_actif` ='1'
UNION
SELECT * FROM `events` WHERE `state` ='1'

Voici l'erreur retournée :

MySQL a répondu: Documentation

#1222 - The used SELECT statements have a different number of columns

A priori les tables n'ont pas le même nombre de colonnes ... Ce qui est le cas, mais c'est bizarre que ça me génère une erreur non ?

RiderFx3
Auteur

Alors cette erreur est corrigée quand j'enleve le signe *.
Je continue sur cette vois et je vous tiens au courant. :)

Comme l'erreur le dit, et comme Huggy t'as montré, tu dois récupérer exactement les mêmes champs dans chacune des 2 requetes.
comme tu vois dans l'exemple d'Huggy, il met explicitement des "as" pour avoir les mêmes noms et le même nombre de champ :

    SELECT nomarticle AS chptexte, datecreate AS chpdate FROM articles WHERE a_actif='1'
    UNION
    SELECT nomevent AS chptexte, datecreateevent AS chpdate FROM events WHERE a_actif='1'

Si tes 2 tables n'ont pas exactement le même nombre et les mêmes noms de colonne, l'étoile "*" ne marchera pas :)

Edit: mais rien ne t'empeche de faire des SELECT "" as ceChampExisteDansLAutreTableUniquement

RiderFx3
Auteur

Effectivement c'est comme ça que j'ai fait, en jouant sur les AS. :)
Merci pour ton aide.

RiderFx3
Auteur

Voilà à quoi ressemble ma requête finale ;)
Merci à vous

SELECT `type_table` AS 'type', `a_id` AS 'id', `a_date_publi` AS 'date', `a_une` AS 'image', `a_contenu` AS 'description', `a_slug` AS 'slug' FROM `articles`
UNION
SELECT `type_table` AS 'type', `id` AS 'id', `date` AS 'date', `image` AS 'image', `description` AS 'description', `slug` AS 'slug' FROM `events`
ORDER BY `date` LIMIT 4

Pour info, tu n'es pas obligé de mettre un "as" si ce n'est pas nécessaire.

"id as id" > "id" suffit

RiderFx3
Auteur

Ok je vais corriger merci je l'avais mis au cas ou. :)