1
votes

Comment puis-je utiliser plusieurs instructions case dans un seul alias dans une instruction SELECT?

Comment puis-je attribuer plusieurs instructions CASE à un seul ALIAS?

En supposant que j'ai les tableaux suivants. Chaque colonne «id» est un bigint et tous les autres champs sont varchar (255). «some_word» est un nom de produit qui a récemment changé de nom en un autre nom, et je dois générer un rapport que toutes les occurrences de «some_word» que nos gestionnaires de contenu utiliseront pour remplacer l'ancien nom par le nouveau nom.

SELECT 
   CASE WHEN c.fullname LIKE '%some_word%'
      THEN c.fullname 
      CASE WHEN c.shortname LIKE '%some_word%'
         THEN c.fullname
      END
   END AS 'Entity Name'
   --repeat for each table
FROM tbl_course c, tbl_assign a, tbl_data_content dc

Je suis obligé de créer une seule instruction SELECT qui renvoie toutes les valeurs de 'some_word' dans toute la base de données comme suit:

--------------------------------------------
| id  | Entity Name     | Entity Type      |
--------------------------------------------
| 1   | some_word       | tbl_course       |
| 788 | Jays Course     | tbl_course       |
| 1   | some_word No. 5 | tbl_assign       |
| 51  | my data         | tbl_data_content | 
| 70  | some_word       | tbl_data_content |
-------------------------------------------- 


3 commentaires

Je ne vois pas le lien entre les noms d'entités et les trois tables pour lesquelles vous avez fourni des exemples de données. Pouvez-vous expliquer ce qui se passe?


@TimBiegeleisen, la colonne 'Nom de l'entité' dans l'ensemble de données renvoyé doit contenir le nom de l'entité tel qu'il le voit dans l'application (c.fullname, a.name et dc.modulename) afin que les utilisateurs qui utiliseront ce rapport puissent faire correspondre les enregistrements aux entités de l'application (Moodle 3.6.5).


Le nom d'entité est l'un des alias que je souhaite utiliser. - J'ai édité le message original pour clarifier cela.


3 Réponses :


0
votes

Une seule requête SELECT (comme dans vraiment un seul SELECT) est probablement impossible ici.

Vous pouvez coder en dur chaque champ de table qui peut contenir some_word dans une requête SELECT et utiliser UNION pour tout combiner dans un seul jeu de résultats.

SELECT [id]
     , [fullname] as [Entity Name]
     , 'tbl_course' as [Entity Type]
  FROM [tbl_course]
 WHERE [fullname] LIKE '%some_word%'

 UNION

SELECT [id]
     , [fullname]
     , 'tbl_course'
  FROM [tbl_course]
 WHERE [shortname] LIKE '%some_word%'

 UNION

SELECT [id]
     , [name]
     , 'tbl_assign'
  FROM [tbl_assign]
 WHERE [name] LIKE '%some_word%'

 UNION

SELECT [id]
     , [name]
     , 'tbl_assign'
  FROM [tbl_assign]
 WHERE [intro] LIKE '%some_word%'

 UNION

SELECT [id]
     , [description] 'tbl_data_content'
  FROM [tbl_data_content]
 WHERE [description] LIKE '%some_word%'

 UNION

SELECT [id]
     , [description] 'tbl_data_content'
  FROM [tbl_data_content]
 WHERE [modulename] LIKE '%some_word%';

Cette requête (qui est formellement une seule requête SQL) devrait donner les résultats de votre question. Cependant, je ne l'ai pas testé.

Vous devrez ajouter vous-même des requêtes SELECT supplémentaires pour d'autres combinaisons de table / champ.

Si vous ne souhaitez pas le coder en dur ou si vous avez besoin de plus de flexibilité, vous pouvez créer un script SQL qui crée / construit dynamiquement la requête ci-dessus. Mais dans ce cas, vous avez toujours besoin d'une table (ou d'une autre source de données) contenant une liste de tous les champs de chaque table pouvant contenir quelque_mot .

J'espère que cela vous aidera.


2 commentaires

Ahh, ça ressemble à ce que je veux! Je ne savais pas que la fonction UNION existait. Je vais essayer ceci et vous le faire savoir ici.


D'ACCORD. :) Oui, UNION peut être utile. Il existe également un UNION ALL , qui conserve les doublons. Et si vous ne voulez que des enregistrements qui correspondent aux deux requêtes, il existe également l'opérateur INTERSECT : SELECT * FROM A INTERSECT SELECT * FROM B affichera tous les enregistrements qui sont tous les deux dans A et en B. Notez que A et B doivent avoir la même structure (même nombre de champs et mêmes types de champs). Et vous pouvez peut-être aussi utiliser SAUF si vous avez besoin de tout de A qui n'est pas dans B. Tout est plus ou moins dérivé de la théorie mathématique des ensembles. La documentation de votre SGBD contiendra beaucoup plus d'informations à ce sujet.



0
votes

VOUS POUVEZ UTILISER PLUSIEURS CONDITIONS DANS UN SEUL CAS COMME CECI

CASE WHEN [CONDITION] THEN [RESULT] 
     WHEN [CONDITION] THEN [RESULT] 
     WHEN ..... THEN [RESULT] 
     ELSE [DEFAULT] 
END

0 commentaires

1
votes

Je suggérerais d'utiliser union all et de normaliser les données dans une sous-requête. Je pense que vous pouvez concaténer les valeurs de la recherche,

select id, entityname, entitytype,
from ((select id, fullname as entityname, 'tbl_course' as entitytype
              concat(fullname, '|', shortname, '|', summary) as tosearch
       from tbl_course
      ) union all
      (select id, name as entityname, 'tbl_course' as entittype
              concat(name, '|', intro) as tosearch
       from tbl_assign
      ) union all
      (select id, description as entityname, 'tbl_data_content' as entittype
              concat(description, '|', modulename) as tosearch
       from tbl_data_content
      )
     ) x
where tosearch like <pattern here>


2 commentaires

Avec UNION ALL, les doublons éventuels ne seront pas éliminés. par exemple, lorsque plusieurs champs dans le même enregistrement contiennent some_word . Sauf si vous spécifiez de quel champ il s'agit, mais peut-être que c'est inutilement trop de détails pour l'OP (car il n'a pas été spécifié dans ses résultats attendus). J'ai envisagé d'utiliser une expression de table ou CTE aussi, mais je n'ai vu aucune valeur ajoutée. Pouvez-vous expliquer pourquoi vous conseillez de «normaliser» les données dans une sous-requête plus complexe et (à mon humble avis) inutile?


Ah. Je vois juste que vous ne devez spécifier le modèle de recherche qu'une seule fois. C'est vraiment très gentil.