2
votes

Regrouper une colonne groupée sans sous-requête

Je pense que cela peut être plus facile à expliquer avec un exemple, alors disons que nous avons une base de données comme celle-ci:

  • Le premier tableau est Interventions , qui stocke l'ID et quoi que ce soit besoins.
  • Le second est Médecins .
  • Le troisième concerne les Outils .
  • Le quatrième est un tableau N-N, qui correspond à chaque intervention avec toutes ses médecins, appelons-le DoctorsOnInterventions
  • Le cinquième est un autre tableau N-N, qui correspond à chaque outil utilisé sur chaque intervention, appelons-le ToolsOnInterventions

Ok, maintenant nous pouvons faire:

+-----------------+------------+-----------------+
| InterventionId  |  Doctors   |      Tools      |
+-----------------+------------+-----------------+
|               1 | Tom, John  | Scalpel, Hammer |
|               2 | Tom, Homer | Hammer, Bulb    |
+-----------------+------------+-----------------+

Et obtenir:

+-----------------+------------+
| InterventionId  |  Doctors   |
+-----------------+------------+
|               1 | Tom, John  |
|               2 | Tom, Homer |
+-----------------+------------+

Mais nous avons besoin pour ajouter une autre colonne, tout comme Doctors, mais avec les outils utilisés dans cette intervention, quelque chose comme ceci:

SELECT InterventionId, STRING_AGG(Doctors.Name, ', ')
FROM Interventions
INNER JOIN Doctors ON Doctors.Id = DoctorsOnInterventions.DoctorId
GROUP BY Intervention.Id, Doctors.Id;

Il serait facile de faire encapsuler le code précédent sur une sous-requête puis en créant un autre groupe par , mais je me demandais s'il y avait un moyen plus correct de le faire car mes tables de base de données ont quelques dizaines de colonnes.


4 commentaires

Qu'est-ce que la fonction STRING () ?


Ce n'est pas un t-sql valide. Je ne connais aucune version de sql qui a STRING comme fonction. Que diriez-vous des définitions de table, des exemples de données et de quelque chose de valide pour une requête?


Quel type de relation existe-t-il entre les tableaux Interventions et Outils? Vous ne pouvez associer des tables que si comment avoir au moins une colonne entre elles


@GordonLinoff l'a corrigé


3 Réponses :


0
votes

Vous pouvez utiliser string_agg () . Je recommanderais des sous-requêtes; apply peut être utilisé:

SELECT i.*, d.doctors, t.tools
FROM Interventions i OUTER APPLY
     (SELECT STRING_AGG(d.name, ',') as doctors
      FROM DoctorsOnInterventions doi JOIN
           Doctors d
           ON d.Id = doi.DoctorId
      WHERE doi.interventionId = i.id
     ) d OUTER APPLY
     (SELECT STRING_AGG(t.name, ',') as tools
      FROM ToolsOnInterventions toi JOIN
           Tools t
           ON t.id = toi.ToolId
      WHERE toi.interventionId = i.id
     ) t ;

Dans les anciennes versions de SQL Server, vous pouvez utiliser la méthode FOR XML PATH de concaténation de chaînes.


0 commentaires

0
votes

Je pense que vous aurez besoin d'une autre table pour les relier alors.

Interventions de table

SELECT InterventionId, STRING(Doctors.Name, ', ')
FROM Interventions I WITH (NOLOCK)
INNER JOIN Doctors D WITH (NOLOCK) ON D.Id = I.DoctorId
INNER JOIN Interventions_tool IT WITH (NOLOCK) ON I.Id = IT.ToolId
GROUP BY I.Id, D.Id;

+-----------------+------------+-----------------+
| InterventionId  |  Doctors   |      Tools      |
+-----------------+------------+-----------------+
|               1 | Tom, John  | Scalpel, Hammer |
|               2 | Tom, Homer | Hammer, Bulb    |
+-----------------+------------+-----------------+

Outils de table

+-----------------+------------+
| InterventionId  |  ToolId    |
+-----------------+------------+
|               1 | 1          |
|               2 | 2          |
+-----------------+------------+

Table Interventions_tool ( nouveau )

+-----------------+----------------+
| InterventionId  |  Doctors       |
+-----------------+----------------+
|               1 | Scalpel, Hammer|
|               2 | Hammer, Bulb   |
+-----------------+----------------+

La requête sera

+-----------------+------------+
| InterventionId  |  Doctors   |
+-----------------+------------+
|               1 | Tom, John  |
|               2 | Tom, Homer |
+-----------------+------------+


2 commentaires

Oui, je l'ai écrit, je l'ai appelé ToolsOnInterventios


@ CarlosLópezMarí Je n'ai pas compris? Avez-vous utilisé la suggestion?



0
votes
SELECT InterventionId, STRING(Doctors.Name, ', '),STRING(Tools.name,',')
FROM Interventions
INNER JOIN Doctors ON Doctors.Id = DoctorsOnInterventions.DoctorId 
INNER JOIN Tools on tools.id = ToolsOnInterventions.toolsid
GROUP BY Intervention.Id, Doctors.Id, tools.id; 

1 commentaires

Si vous groupez par ces 3, vous obtiendrez pour chaque médecin toutes les combinaisons d'outils utilisées, ce n'est pas ce dont j'ai besoin.