【问题标题】:Multiple SQL left join return same counted value if there is same date in two tables如果两个表中的日期相同,则多个 SQL 左连接返回相同的计数值
【发布时间】:2021-01-11 11:21:06
【问题描述】:

我有以下表格:

日历(用于报告)

表格

CREATE TABLE `calendars` (
  `date` date NOT NULL,
  PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

样本

INSERT INTO `calendars`(`date`)
VALUES
 ('2020-05-20'),
 ('2020-05-21'),
 ('2020-05-22'),
 ('2020-05-23');

个人

表格

CREATE TABLE `individuals` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `accepted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=705 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

样本

INSERT INTO `individuals`(`name`, `accepted_at`)
VALUES
 ('Zen', '2020-05-20'),
 ('John', '2020-05-21'),
 ('Jane', '2020-05-21'),
 ('Mary', '2020-05-21'),
 ('Ben', '2020-05-22');

组织

表格

CREATE TABLE `organizations` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `accepted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=705 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

样本

INSERT INTO `organizations`(`name`, `accepted_at`)
VALUES
 ('Ethan', '2020-05-21');

我正在尝试计算两个表(个人和组织)中具有给定日期的行,但如果表中的日期相同,则仅返回最高计数值。

我一直在使用的查询:

SELECT 
    `calendars`.`date` as 'date',
    COUNT(`individuals`.`accepted_at`) as 'individuals',
    COUNT(`organizations`.`accepted_at`) as 'organizations'
FROM `calendars`
LEFT JOIN `individuals`
ON DATE(`calendars`.`date`) = DATE(`individuals`.`accepted_at`)
LEFT JOIN `organizations`
ON DATE(`calendars`.`date`) = DATE(`organizations`.`accepted_at`)
WHERE DATE(`calendars`.`date`) BETWEEN "2020-05-20" AND "2020-05-30"
GROUP BY `date`;

结果

【问题讨论】:

  • 这不是已发布样本数据的结果,请将样本数据发布为我们可以使用的文本,而不是我们不能使用的图像;
  • @P.Salmon 刚刚添加了表架构和示例数据

标签: mysql group-by count left-join where-clause


【解决方案1】:

连接是累积的,所以给定

drop table if exists t1;
drop table if exists t;

create table t(accepted_at date);
create table t1(accepted_at date);

insert into t values ('2020-05-20'),('2020-05-20'),('2020-05-21');
insert into t1 values ('2020-05-21'),('2020-05-21'),('2020-05-21');

SELECT 
    `calendars`.`dte` as 'date',`individuals`.`accepted_at`,`organizations`.`accepted_at`
FROM dates `calendars`
LEFT JOIN t `individuals`
ON DATE(`calendars`.`dte`) = DATE(`individuals`.`accepted_at`)
LEFT JOIN t1 `organizations`
ON DATE(`calendars`.`dte`) = DATE(`organizations`.`accepted_at`)
WHERE DATE(`calendars`.`dte`) BETWEEN "2020-05-20" AND "2020-05-21";

返回

+------------+-------------+-------------+
| date       | accepted_at | accepted_at |
+------------+-------------+-------------+
| 2020-05-21 | 2020-05-21  | 2020-05-21  |
| 2020-05-21 | 2020-05-21  | 2020-05-21  |
| 2020-05-21 | 2020-05-21  | 2020-05-21  |
| 2020-05-20 | 2020-05-20  | NULL        |
| 2020-05-20 | 2020-05-20  | NULL        |
+------------+-------------+-------------+
5 rows in set (0.002 sec)

您可以合并 2 个表并有条件地聚合

SELECT 
    `dte` as 'date',
    sum(case when srce = 'i'  then 1 else 0 end) as 'individuals',
    sum(case when srce = 'o'  then 1 else 0 end) as 'organizations'
from dates
left join
(
select 'i' as srce,accepted_at dt from t where accepted_at  between '2020-05-20' and '2020-05-21'
union all
select 'o' as srce,accepted_at from t1 where accepted_at  between '2020-05-20' and '2020-05-21'
) as s on s.dt = dates.dte
where dte between '2020-05-20' and '2020-05-21'
GROUP BY `dte` ;

+------------+-------------+---------------+
| date       | individuals | organizations |
+------------+-------------+---------------+
| 2020-05-20 |           2 |             0 |
| 2020-05-21 |           1 |             3 |
+------------+-------------+---------------+
2 rows in set (0.003 sec)

【讨论】:

  • 谢谢哥们。我花了一个小时来理解您的查询,而且我不熟悉别名词。这就是为什么。 ^_^
猜你喜欢
  • 2022-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 2020-12-06
  • 2023-01-31
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多