如果某个列存在,则选择特定的行,否则选择所有行。

我正在编写一个脚本,用于获取几个表的行数,但是对于某些表,我只想获取设置了标志位的行数(在这种情况下,active=1)。有没有办法可以在一次查询中完成这个操作? 例如: 表users有一个名为active的列 表clients没有一个名为active的列 我想获取active=1的用户数量,并且只获取clients的数量。 在你说“只需硬编码”之前,这是一个将进入Python脚本的查询,可能会在许多不同的数据库上运行,而我无法知道我的脚本将选择哪些表以及它们是否有一个名为active的列。我更希望只使用一个查询来完成所有操作,而不是两个单独的查询,并依靠MySQL抛出错误来告诉我要使用另一个查询。

用户中有一个 clientid,它引用了一个客户。 - Matt S.
3个回答

我的第一個想法是先使用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 

使用仅限于users表的UserID客户总数统计:

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;
对于没有active列的users表:
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;