多个SQL left join return 如果两个表中有相同的日期则相同的计数值

Multiple SQL left join return same counted value if there is same date in two tables

我有以下表格:

日历(用于报告)

Table

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');

个人

Table

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');

组织

Table

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');

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

我一直在使用的查询:

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`;

结果

加入是累积的,所以给出

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";

returns

+------------+-------------+-------------+
| 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)