web-dev-qa-db-fra.com

Comment sélectionner des lignes spécifiques si une colonne existe ou toutes les lignes si une colonne n'existe pas

J'écris un script qui obtient un nombre de lignes pour quelques tables, mais pour certaines tables, je veux seulement obtenir un nombre de lignes où un indicateur est défini (dans ce cas, actif = 1). Existe-t-il un moyen de le faire dans une seule requête?

Par exemple:

La table users a une colonne appelée active

La table clients n'a pas de colonne appelée active

Je veux obtenir un nombre d'utilisateurs où active = 1 et simplement obtenir un nombre de clients.

Avant de dire "il suffit de coder en dur", il s'agit d'une requête qui va dans un script python qui pourrait être exécuté sur de nombreuses bases de données différentes et je n'ai aucun moyen de savoir quelles tables mon script sélectionnera et s'ils ont une colonne appelée active, et je préférerais avoir une seule requête pour tout faire au lieu de deux requêtes distinctes et en s'appuyant sur mysql pour lancer une erreur, donc je sais utiliser l'autre.

23
Matt S.

Ma première pensée serait d'utiliser le INFORMATION_SCHEMA d'abord, pour que vous sachiez (dans une requête pour toutes les tables de l'instance MySQL) quelles tables ont une colonne active, puis utilisez ces informations pour construire vos requêtes. Et c'est probablement l'approche la plus sensée.

Il existe cependant une autre méthode délicate qui fonctionne, que la table ait ou non une telle colonne:

SELECT 
  ( SELECT COUNT(*)
    FROM TableName AS t
    WHERE active = 1
  ) AS cnt
FROM
  ( SELECT 1 AS active
  ) AS dummy ;

Testé à SQL-Fiddle Comment ça marche?

Si la table a une colonne nommée active, la requête est "traduite" comme si elle avait:

    WHERE t.active = 1

Si la table n'a pas de colonne nommée active, la requête est "traduite" comme si elle avait:

    WHERE dummy.active = 1         -- which is true 
51
ypercubeᵀᴹ

Nombre de clients par ID utilisateur avec Grand Total utilisant uniquement la table users:

SELECT
    IFNULL(u.id,'Total') UserID,
    COUNT(u.clientid) ClientCount
FROM users u
WHERE u.active = 1
GROUP BY u.id WITH ROLLUP;

Si la table des clients a supprimé des enregistrements, procédez comme suit:

SELECT
    IFNULL(u.id,'Total') UserID,
    COUNT(c.id) ClientCount
FROM users u INNER JOIN clients c
ON u.clientid = c.id
WHERE u.active = 1
GROUP BY u.id WITH ROLLUP;

Pour les tables users qui n'ont pas de colonne active:

SELECT
    IFNULL(u.id,'Total') UserID,
    COUNT(u.clientid) ClientCount
FROM users u
GROUP BY u.id WITH ROLLUP;

ou

SELECT
    IFNULL(u.id,'Total') UserID,
    COUNT(c.id) ClientCount
FROM users u INNER JOIN clients c
ON u.clientid = c.id
GROUP BY u.id WITH ROLLUP;

Vous devez exécuter ces requêtes sur chaque base de données et UNION ALL Les resultats.

Si vous souhaitez exploiter la base de données INFORMATION_SCHEMA, voici une supposition sauvage:

SELECT COUNT(1) INTO @hasactive
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'users'
AND column_name = 'active';
SELECT
    IFNULL(u.id,'Total') UserID,
    COUNT(u.clientid) ClientCount
FROM users u
WHERE IF(@hasactive=1,u.active=1,1)=1
GROUP BY u.id WITH ROLLUP;

Essaie !!!

3
RolandoMySQLDBA

Je voudrais compléter la réponse du @ ypercubeᵀᴹ, mais je ne peux pas écrire de commentaires à cause des restrictions.

Si vous ne savez pas quel nom de colonne est utilisé et que vous devez obtenir sa valeur maximale, vous pouvez le faire:

SELECT
    ( SELECT
          max(ISNULL(updateTime, null)) + max(ISNULL(updDT, null))
          FROM tableName as t
    ) AS maxUpdateDT
FROM (SELECT 0 AS updateTime, 0 as updDT) AS dummy;
1
Dev9