Як вибрати конкретні рядки, якщо стовпець існує, або всі рядки, якщо стовпець відсутній


23

Я пишу сценарій, який отримує кількість рядків для декількох таблиць, однак для деяких таблиць я хочу отримати лише кількість рядків, де встановлено прапор (у цьому випадку active = 1). Чи є спосіб це зробити за один запит?

Наприклад:

У таблиці usersє стовпець, який називається активним

У таблиці clientsнемає стовпця, який називається активним

Я хочу отримати кількість користувачів, де активний = 1 і просто отримати кількість клієнтів.

Перш ніж сказати "просто жорсткий код це", це запит, який відбувається всередині сценарію python, який можна запустити на безлічі різних баз даних, і я не можу знати, які таблиці буде вибирати мій скрипт, і якщо у них є стовпець, що називається active, і Я вважаю за краще мати лише один запит, щоб зробити це замість двох окремих, і покладатися на mysql, щоб викинути помилку, щоб я знав використовувати інший.


є користувач, який посилається на клієнта
Matt S.

Відповіді:


50

Першою моєю думкою було б скористатися INFORMATION_SCHEMAпершою, тому ви дізнаєтесь (за один запит для всіх таблиць в екземплярі MySQL), у яких таблицях activeстовпчик, а потім використаєте цю інформацію для побудови запитів. І це, мабуть, самий розумний підхід.

Є ще один, хитрий спосіб, хоча це працює незалежно від того, чи є у таблиці такий стовпець чи ні:

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

Тестовано на SQL-Fiddle Як це працює?

Якщо в таблиці є стовпець з назвою active, запит "перекладається" так, ніби він мав:

    WHERE t.active = 1

Якщо в таблиці немає стовпця з назвою active, запит "перекладається" так, ніби він мав:

    WHERE dummy.active = 1         -- which is true 

3

Кількість клієнтів на UserID з Grand Total, використовуючи лише usersтаблицю:

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

Якщо таблиця клієнтів видалила записи, зробіть це:

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;

Для usersтаблиць, у яких немає activeстовпця:

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

або

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;

Вам потрібно буде запустити ці запити проти кожної бази даних та UNION ALLрезультатів.

Якщо ви хочете використовувати базу даних INFORMATION_SCHEMA, ось ось дивна здогадка:

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;

Спробувати !!!


1

Я хотів би доповнити відповідь @ ypercubeᵀᴹ, але я не можу писати коментарі через обмеження.

Якщо ви не знаєте, яке ім’я стовпця використовується, і вам потрібно отримати його максимальне значення, ви можете зробити це:

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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.