いくつかのテーブルの行数を取得するスクリプトを書いていますが、一部のテーブルでは、フラグが設定されている(この場合はactive = 1)行の数のみを取得したい場合があります。これを1つのクエリで実行する方法はありますか?
例えば:
テーブルusers
には、アクティブと呼ばれる列があります
テーブルclients
には、アクティブと呼ばれる列がありません
Active = 1のユーザーの数を取得し、クライアントの数を取得したいのですが。
「ただハードコードする」と言う前に、これはpythonスクリプト内で実行されるクエリであり、多数の異なるデータベースで実行でき、スクリプトが選択するテーブルを知る方法がありません。そして、それらにactive
という列があり、2つの個別のクエリではなく、1つのクエリですべてを実行し、mysqlを使用してエラーをスローするので、もう1つのクエリを使用することができます。
私の最初の考えは、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
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;
試してみる !!!
@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;