web-dev-qa-db-ja.com

列が存在する場合に特定の行を選択する方法、または列が存在しない場合にすべての行を選択する方法

いくつかのテーブルの行数を取得するスクリプトを書いていますが、一部のテーブルでは、フラグが設定されている(この場合はactive = 1)行の数のみを取得したい場合があります。これを1つのクエリで実行する方法はありますか?

例えば:

テーブルusersには、アクティブと呼ばれる列があります

テーブルclientsには、アクティブと呼ばれる列がありません

Active = 1のユーザーの数を取得し、クライアントの数を取得したいのですが。

「ただハードコードする」と言う前に、これはpythonスクリプト内で実行されるクエリであり、多数の異なるデータベースで実行でき、スクリプトが選択するテーブルを知る方法がありません。そして、それらにactiveという列があり、2つの個別のクエリではなく、1つのクエリですべてを実行し、mysqlを使用してエラーをスローするので、もう1つのクエリを使用することができます。

23
Matt S.

私の最初の考えは、INFORMATION_SCHEMA最初に、(MySQLインスタンスのすべてのテーブルに対する1つのクエリで)どのテーブルにactive列があるかを確認し、その情報を使用してクエリを作成します。そして、これはおそらく最も健全なアプローチです。

テーブルがそのような列を持っているかどうかに関係なく機能しますが、もう1つ、トリッキーな方法があります。

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 
51
ypercubeᵀᴹ

usersテーブルのみを使用した総計を持つユーザーIDあたりのクライアント数:

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;

試してみる !!!

3
RolandoMySQLDBA

@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;
1
Dev9