8722 sujets

Développement web côté serveur, CMS

Bonjour à tous,

J'ai un petit souci de requête SQL que je vais essayer de vous exposer, c'est pas simple...

Je souhaite récupérer une liste de contacts (référent du dossier) faisant partie d'un dossier particulier (ce dossier n'est pas un dossier informatique mais un dossier contenant des données concernant l'obtention d'un prêt bancaire).

Il y a plusieurs intervenants sur ce dossier qui sont des contacts et tous les contacts de l'entreprise sont dans une table 'contacts'.
Il y a également un référent du dossier (qui est aussi un contact) que je veux afficher.

Les dossiers sont dans une table 'dossiers'.

J'ai une table de liaison qui lie les contacts aux dossiers sur lesquels ils sont présents (link_contacts_dossiers).

On filtre les contacts selon leur fonction (fonction1, fonction2...) et les dossiers de ces contacts en fonction de l'utilisateur connecté (qui doit être un intervenant sur le dossier).

Mais j'aimerai sur une seule fonction (la fonction1) afficher tous les contacts de cette fonction et non plus seulement le contact lié au dossier.

Voici ma requête actuelle (en code Codeigniter mais derrière ça génère une requête SQL standard) :

<?php
//SELECT infos du contact
$this->db->select('Contact.FirstName, Contact.LastName');

//FROM la table des contacts
$this->db->from('contacts as Contact');

//JOIN la table des dossiers dans lesquels le contact est le référent
$this->db->join(
  'dossiers as user_dossiers',
  'user_dossiers.contact_referent = Contact.Id');

//JOIN la table de liaison permettant de lier les dossiers et
//les contacts présents sur un dossier.
//Ca va nous permettre de n'afficher que les contacts référents
//des dossiers sur lesquels l'utilisateur connecté est présent.
$this->db->join(
  'link_contacts_dossiers as auth_user',
  'auth_user.dossier_id = user_dossiers.Id');

//WHERE IN filtre les contacts référents suivant leur fonction
$this->db->where_in('Contact.fonction', array('fonction1', 'fonction2'));

//WHERE $user_sess_id est l'id du contact connecté,
//nous filtrons la table de liaison pour n'afficher que les dossiers
//(et du coup les contacts référents) sur lesquels cet utilisateur est présent
$this->db->where('auth_user.contact_id = "' . $user_sess_id . '"');


Voici la requête générée :

SELECT `Contact`.`FirstName`, `Contact`.`LastName`
FROM `prp_contacts` as `Contact`
JOIN `prp_dossiers` as `user_dossiers`
  ON `user_dossiers`.`contact_referent` = `Contact`.`Id`
JOIN `prp_link_contacts_dossiers` as `auth_user`
  ON `auth_user`.`dossier_id` = `user_dossiers`.`Id`
WHERE `Contact`.`fonction` IN('fonction1', 'fonction2')
  AND `auth_user`.`contact_id` = "0035700001vwVaKAAU"


Cette requête fonctionne très bien et ne m'affiche bien que les contacts des référents des dossiers de l'utilisateur connecté, mais...

QUESTION : comment faire pour que j'affiche TOUS les contacts ayant pour fonction 'fonction1' ? Même ceux qui ne sont pas sur les dossiers de l'utilisateur connecté.

Merci pour vos réponses
Modérateur
Salut,

A ce que j'ai pu comprendre, tu supprimes la jointure tout simplement et tu fais une requête basique.

SELECT
    FirstName,
    LastName
FROM
    contacts
WHERE
    fonction = 'fonction1'


Au passage, j'ai l'impression que ta table contact n'est pas normalisée. Ce qui a pour effet, redondance, doublon, etc. Je pense notamment au champ fonction. Vu ta description, je pense que tu devrais extraire les données du champ fonction et en faire une table à part entière liée à contacts. Smiley cligne
Merci Niuxe pour ta réponse et en effet ma question n'était pas assez complète.
La question aurait dû être :

Comment faire pour que j'affiche TOUS les contacts ayant pour fonction 'fonction1' EN PLUS de ceux filtrés par ailleurs ? Même ceux qui ne sont pas sur les dossiers de l'utilisateur connecté.

En fait, j'ai une solution : UNION. Je fais mes 2 requêtes filtrée et pas filtrée (uniquement sur fonction1) puis je lie les 2 par un UNION (http://sql.sh/cours/union) mais j'étais retissant à utiliser cette méthode car Codeigniter ne l'implémente pas dans son pseudo ORM et j'ai beaucoup d'autres clauses (where, orderby et join) sur cette requête. Mais je crois devoir m'y coller quand même...

SELECT
    `Contact`.`FirstName`,
    `Contact`.`LastName`
FROM
    `prp_contacts` as `Contact`
        JOIN `prp_dossiers` as `user_dossiers`
            ON `user_dossiers`.`contact_referent` = `Contact`.`Id`
        JOIN `prp_link_contacts_dossiers` as `auth_user`
            ON `auth_user`.`dossier_id` = `user_dossiers`.`Id`
WHERE
    `Contact`.`fonction` IN('fonction1', 'fonction2')
    AND `auth_user`.`contact_id` = "0035700001vwVaKAAU"
 
UNION
 
SELECT `FirstName`, `LastName`
FROM `prp_contacts`
WHERE `fonction` = 'fonction1';


Cette partie est résolue.

Je rebondis cependant sur ta remarque intéressante sur le manque potentiel de normalisation de ma table 'contacts'. Comment vois-tu qu'il y aurait un souci à ce niveau ?
J'ai une colonne 'contacts.fonction' dans laquelle j'ai une valeur (VARCHAR), vaudrait-il mieux avoir une table 'fonctions' avec une colonne 'fonctions.contact_id' et une colonne 'fonctions.fonction_name' ?
Modifié par MatthieuR (25 Nov 2015 - 13:51)
Modérateur
MatthieuR a écrit :

Je rebondis cependant sur ta remarque intéressante sur le manque potentiel de normalisation de ma table 'contacts'. Comment vois-tu qu'il y aurait un souci à ce niveau ?
J'ai une colonne 'contacts.fonction' dans laquelle j'ai une valeur (VARCHAR), vaudrait-il mieux avoir une table 'fonctions' avec une colonne 'fonctions.contact_id' et une colonne 'fonctions.fonction_name' ?


une image vaut mieux qu'un long discours n'est ce pas ?
http://img15.hostingpics.net/thumbs/mini_688374diasgbdrmatthieur.png

Ainsi, tes 2 tables seront intègres et tu éviteras doublons, redondances, etc. Là dans ta table tu pourrais avoir avoir une ligne du style : Madame Jeanine Michu - secrétaire de direction.
tu pourrais avoir une autre ligne :
Madame Ginette Dupont - Secrétaire de Direction
en continuant dans le même esprit, je pourrais avoir cela aussi :
Madame Jeanine Michu - SECRETAIRE DE DIRECTION.

Je pense qu'avec l'exemple ci-dessus, tu commences à comprendre pourquoi la table n'est pas normalisée. Avec ce genre de données, ça va être simple de faire un SELECT sur les secrétaire de direction....

D'une manière générale, il vaut mieux plusieurs petites tables liées entres elles qu'une énorme table aux données improbables.


ps : je t'ai fait ça très rapidement, mais je t'ai fait ce schémas pour que tu comprennes.
Modifié par niuxe (25 Nov 2015 - 15:40)
Je comprends bien le raisonnement et l'applique pas mal par ailleurs cependant, je ne l'appliquais pas ici car cette table (et bien d'autres) sont mises à jour par un CRON toutes les 10 min avec les données d'une autre base de données (Salesforce pour ne pas nommer le service...) et j'ai déjà une vérification des doublons de ce côté...
C'est dans le cadre d'une application connectée à Salesforce à qui je me connecte via leur API REST.

Merci en tous cas pour tes explications claires et précises.
Modifié par MatthieuR (25 Nov 2015 - 16:08)
Modérateur
MatthieuR a écrit :
Je comprends bien le raisonnement et l'applique pas mal par ailleurs cependant, je ne l'appliquais pas ici car cette table (et bien d'autres) sont mises à jour par un CRON toutes les 10 min avec les données d'une autre base de données (Salesforce pour ne pas nommer le service...) et j'ai déjà une vérification des doublons de ce côté...
C'est dans le cadre d'une application connectée à Salesforce à qui je me connecte via leur API REST.

Merci en tous cas pour tes explications claires et précises.


Ah ok, je comprends mieux le contexte. J'ai eu un peu la même démarche une fois. Les données en amont étaient intègres et en les réutilisant côté client on ne se souciait plus de cet aspect (Introducing Web SQL Databases).
Modifié par niuxe (26 Nov 2015 - 00:17)