Select 单次查询总行数,总field1 = 1,总field1 = 0?
Select total of rows, total of field1 = 1, total of field1 = 0 in a single query?
我有以下 table :
id | command_id | started_at | ended_at | rows_involved | completed
-----------------------------------------------------------------------------------------------
1 | 1 | 2015-05-20 12:02:25 | 2015-05-20 12:02:28 | 1 | 1
2 | 1 | 2015-05-20 12:02:47 | NULL | NULL | 0
3 | 1 | 2015-05-20 12:11:10 | NULL | NULL | 0
4 | 1 | 2015-05-20 12:11:46 | NULL | NULL | 0
5 | 1 | 2015-05-20 12:12:25 | NULL | NULL | 0
我想获取 started_at is '2015-05-20' AND commande_id = 1
行的 COUNT 行,我想得到 2 个小计,1 是这些行的总数,其中 completed = 1
,1 是这些行的总数,其中completed = 0
.
预期的数据集如下:
array(4) {
["totalRows"]=> 5
["name"]=> "evo:send_post_registration_mail_1"
["totalCompleted"] => 1
["totalUncompleted"] => 4
}
"name" 列不重要,是与 command_id 字段上的另一个 table 的连接。
我当前的查询如下,但它没有获取 2 个小计:
SELECT COUNT(s0_.id) AS totalRows, s1_.name AS name
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id
我可以在单个查询中获取这 2 个小计吗?
试试这个:
SELECT COUNT(s0_.id) AS totalRows, s1_.name AS name,
(select count(S2_.id) from sf_command_executions S2_ where s0_.command_id=S2_.command_id and s2_.completed = 1) AS totalCompleted,
(select count(S2_.id) from sf_command_executions S2_ where s0_.command_id=S2_.command_id and s2_.completed = 0) AS totalUncompleted
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id
您可以使用条件聚合。在您的 SELECT 列表中使用这样的表达式...
SELECT ...
, SUM(IF(s0_.completed=1,1,0)) AS tot_completed_1
, SUM(IF(s0_.completed=0,1,0)) AS tot_completed_0
您可以使用(更符合 ANSI 标准的)CASE
表达式实现相同的目的:
, SUM(CASE WHEN s0_.completed = 1 THEN 1 ELSE 0 END) AS tot_completed_1
或者您可以使用更短的 MySQL shorthand,因为布尔表达式 return 值为 1、0 或 NULL:
, SUM(s0_.completed=1) AS tot_completed_1
编辑
以下内容未解决您提出的问题(请参阅上文了解您提出的问题的答案)。但我想指出 started_at
列上的谓词(即 WHERE
子句)。
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
^^^^^^^^^^^^ ^^^^^^^^^^^^
围绕列引用的 DATE_FORMAT
函数阻止 MySQL 使用索引范围扫描操作来满足该谓词。
也就是说,MySQL 必须在 table 中的每个 行的 上计算该函数,然后将表达式的结果与文字进行比较值。
如果 started_at
被定义为 DATETIME
或 TIMESTAMP
,我们可以将其重写为等效条件,但在 空 started_at
列。这将允许 MySQL 使用索引范围扫描操作。例如,我们可以这样写相同的行:
WHERE s0_.started_at >= '2015-05-20'
AND s0_.started_at < '2015-05-20' + INTERVAL 1 DAY
如果 started_at
定义为 DATE
,我们可以通过相等比较来引用裸列。不需要 DATE_FORMAT
函数。
如果我们必须使用函数进行某种类型的转换以便比较值,我们更愿意使用函数来环绕文字而不是列引用。围绕文字,该函数只需计算一次。
在这种情况下实际上不需要这样做,只是作为将文字包装在函数中的示例:
WHERE s0_.started_at >= STR_TO_DATE('2015-05-20','%Y-%m-%d')
AND s0_.started_at < STR_TO_DATE('2015-05-20','%Y-%m-%d') + INTERVAL 1 DAY
(再次)请注意,实际上并不需要使用 STR_TO_DATE
函数;这只是展示一种模式。如果我们确实需要进行转换,我们更希望在字面而不是在列上进行转换,以允许 MySQL 使用 started_at
上的可用索引。
您可以使用条件总和作为
SELECT
COUNT(s0_.id) AS totalRows,
s1_.name AS name ,
sum(s0_.completed=1) as totalCompleted,
sum(s0_.completed=0) as totalUncompleted
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id
我有以下 table :
id | command_id | started_at | ended_at | rows_involved | completed
-----------------------------------------------------------------------------------------------
1 | 1 | 2015-05-20 12:02:25 | 2015-05-20 12:02:28 | 1 | 1
2 | 1 | 2015-05-20 12:02:47 | NULL | NULL | 0
3 | 1 | 2015-05-20 12:11:10 | NULL | NULL | 0
4 | 1 | 2015-05-20 12:11:46 | NULL | NULL | 0
5 | 1 | 2015-05-20 12:12:25 | NULL | NULL | 0
我想获取 started_at is '2015-05-20' AND commande_id = 1
行的 COUNT 行,我想得到 2 个小计,1 是这些行的总数,其中 completed = 1
,1 是这些行的总数,其中completed = 0
.
预期的数据集如下:
array(4) {
["totalRows"]=> 5
["name"]=> "evo:send_post_registration_mail_1"
["totalCompleted"] => 1
["totalUncompleted"] => 4
}
"name" 列不重要,是与 command_id 字段上的另一个 table 的连接。
我当前的查询如下,但它没有获取 2 个小计:
SELECT COUNT(s0_.id) AS totalRows, s1_.name AS name
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id
我可以在单个查询中获取这 2 个小计吗?
试试这个:
SELECT COUNT(s0_.id) AS totalRows, s1_.name AS name,
(select count(S2_.id) from sf_command_executions S2_ where s0_.command_id=S2_.command_id and s2_.completed = 1) AS totalCompleted,
(select count(S2_.id) from sf_command_executions S2_ where s0_.command_id=S2_.command_id and s2_.completed = 0) AS totalUncompleted
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id
您可以使用条件聚合。在您的 SELECT 列表中使用这样的表达式...
SELECT ...
, SUM(IF(s0_.completed=1,1,0)) AS tot_completed_1
, SUM(IF(s0_.completed=0,1,0)) AS tot_completed_0
您可以使用(更符合 ANSI 标准的)CASE
表达式实现相同的目的:
, SUM(CASE WHEN s0_.completed = 1 THEN 1 ELSE 0 END) AS tot_completed_1
或者您可以使用更短的 MySQL shorthand,因为布尔表达式 return 值为 1、0 或 NULL:
, SUM(s0_.completed=1) AS tot_completed_1
编辑
以下内容未解决您提出的问题(请参阅上文了解您提出的问题的答案)。但我想指出 started_at
列上的谓词(即 WHERE
子句)。
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
^^^^^^^^^^^^ ^^^^^^^^^^^^
围绕列引用的 DATE_FORMAT
函数阻止 MySQL 使用索引范围扫描操作来满足该谓词。
也就是说,MySQL 必须在 table 中的每个 行的 上计算该函数,然后将表达式的结果与文字进行比较值。
如果 started_at
被定义为 DATETIME
或 TIMESTAMP
,我们可以将其重写为等效条件,但在 空 started_at
列。这将允许 MySQL 使用索引范围扫描操作。例如,我们可以这样写相同的行:
WHERE s0_.started_at >= '2015-05-20'
AND s0_.started_at < '2015-05-20' + INTERVAL 1 DAY
如果 started_at
定义为 DATE
,我们可以通过相等比较来引用裸列。不需要 DATE_FORMAT
函数。
如果我们必须使用函数进行某种类型的转换以便比较值,我们更愿意使用函数来环绕文字而不是列引用。围绕文字,该函数只需计算一次。
在这种情况下实际上不需要这样做,只是作为将文字包装在函数中的示例:
WHERE s0_.started_at >= STR_TO_DATE('2015-05-20','%Y-%m-%d')
AND s0_.started_at < STR_TO_DATE('2015-05-20','%Y-%m-%d') + INTERVAL 1 DAY
(再次)请注意,实际上并不需要使用 STR_TO_DATE
函数;这只是展示一种模式。如果我们确实需要进行转换,我们更希望在字面而不是在列上进行转换,以允许 MySQL 使用 started_at
上的可用索引。
您可以使用条件总和作为
SELECT
COUNT(s0_.id) AS totalRows,
s1_.name AS name ,
sum(s0_.completed=1) as totalCompleted,
sum(s0_.completed=0) as totalUncompleted
FROM sf_command_executions s0_
INNER JOIN sf_commands s1_ ON (s1_.id = s0_.command_id)
WHERE DATE_FORMAT(s0_.started_at,'%Y-%m-%d') = '2015-05-20'
GROUP BY s0_.command_id