MySQL使用不同的值优化查询计数,如果没有行,则使用NULL

MySQL使用不同的值优化查询计数,如果没有行,则使用NULL,mysql,query-optimization,Mysql,Query Optimization,我需要从一个时间少于其他时间的时刻表中获得不同运动员的数量。但棘手的是,如果根本没有时间进行比较,我需要得到NULL作为回报 让我举个例子: CREATE TABLE `teams` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO teams VALUES (NULL, 'Texas'), (NULL,'Oklahoma'

我需要从一个时间少于其他时间的时刻表中获得不同运动员的数量。但棘手的是,如果根本没有时间进行比较,我需要得到NULL作为回报

让我举个例子:

CREATE TABLE `teams` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO teams 
VALUES (NULL, 'Texas'), (NULL,'Oklahoma');

mysql> select * from teams;
+----+----------+
| id | name     |
+----+----------+
|  1 | Texas    |
|  2 | Oklahoma |
+----+----------+


CREATE TABLE `times` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `team_id` int(11) NOT NULL,
  `time` decimal(8,2) NOT NULL,
  `athlete` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `team_id` (`team_id`)
);

INSERT INTO times VALUES 
  (NULL, 1, 19.10, 'Dave'),
  (NULL, 1, 19.09, 'Dave'),
  (NULL, 1, 19.07, 'Dave'),
  (NULL, 1, 19.56, 'John'),
  (NULL, 1, 19.60, 'John'),
  (NULL, 1, 19.75, 'John');

mysql> select * from times;
+----+---------+-------+---------+
| id | team_id | time  | athlete |
+----+---------+-------+---------+
|  1 |       1 | 19.10 | Dave    |
|  2 |       1 | 19.09 | Dave    |
|  3 |       1 | 19.07 | Dave    |
|  4 |       1 | 19.56 | John    |
|  5 |       1 | 19.60 | John    |
|  6 |       1 | 19.75 | John    |
+----+---------+-------+---------+
到目前为止,我们有两个队。第一队有两名运动员,共6次,第二队分别没有运动员和2次

如果我想知道德克萨斯州有多少运动员的速度超过19.50,我可以做:

SELECT COUNT(DISTINCT athlete) FROM times WHERE time < 19.50 and team_id = 1;
+-------------------------+
| COUNT(DISTINCT athlete) |
+-------------------------+
|                       1 |
+-------------------------+
这也是正确的,因为我们有两名来自德克萨斯州的运动员

但如果我想检查一下:有多少俄克拉何马州的运动员跑得比19.00快

这是正确的,如果我在德克萨斯州测试它,我得到:

问题是,这是计数时间,而不是不同的运动员,因此对于德克萨斯州,我将得到错误的计数

SELECT SUM(CASE 
  WHEN time < 19.50 
    THEN 1 
    ELSE 0 
  END) as count
FROM `times`
WHERE team_id = 1;

+-------+
| count |
+-------+
|     3 |
+-------+
我比19.50快3倍,而不是比19.50快1个运动员。

怎么样

SELECT a.name
     , MAX(b.athlete < 19.50) faster 
  FROM teams a 
  LEFT 
  JOIN times b 
    ON b.team_id = a.id 
 GROUP BY a.name;
那么

SELECT a.name
     , MAX(b.athlete < 19.50) faster 
  FROM teams a 
  LEFT 
  JOIN times b 
    ON b.team_id = a.id 
 GROUP BY a.name;

好的,我想我找到了一个解决方案,它又有一个子查询,但至少我不需要重复所有的过滤器两次,如果没有更好的,现在就可以满足我了。这是:

SELECT
  SUM(CASE WHEN a.time < 19.00 THEN 1 ELSE 0 END) as count
FROM (
  SELECT athlete, min(time) as time 
  FROM times 
  WHERE team_id = 2 group by athlete
) a;

通过这种方式,我为团队2获取空值,为团队1获取0。好的,我想我找到了一个解决方案,该解决方案又有一个子查询,但至少我不需要重复所有的过滤器两次,如果没有更好的过滤器,现在就可以满足我了。这是:

SELECT
  SUM(CASE WHEN a.time < 19.00 THEN 1 ELSE 0 END) as count
FROM (
  SELECT athlete, min(time) as time 
  FROM times 
  WHERE team_id = 2 group by athlete
) a;

通过这种方式,我为团队2获取NULL,为团队1获取0

“19.50”是一个字符串。19.50是一个数字mysql正确地将“19.50”转换为数字。不管怎样,19.50是一个字符串。19.50是一个数字mysql正确地将“19.50”转换为数字。不过修正了。很好的技巧,但是如果我用20.00改19.50,我需要得到2作为计数,因为有两个运动员比20.00快。我想我找到了一个解决方案,我会在几分钟后发布。很好的技巧,但是如果我用20.00改19.50,我需要得到2作为计数,因为有两名运动员的速度超过20.00。我想我找到了一个解决方案,我会在几分钟后发布。
SELECT SUM(CASE 
  WHEN time < 19.50 
    THEN 1 
    ELSE 0 
  END) as count
FROM `times`
WHERE team_id = 1;

+-------+
| count |
+-------+
|     3 |
+-------+
SELECT a.name
     , MAX(b.athlete < 19.50) faster 
  FROM teams a 
  LEFT 
  JOIN times b 
    ON b.team_id = a.id 
 GROUP BY a.name;
SELECT
  SUM(CASE WHEN a.time < 19.00 THEN 1 ELSE 0 END) as count
FROM (
  SELECT athlete, min(time) as time 
  FROM times 
  WHERE team_id = 2 group by athlete
) a;