我需要在MySQL上运行以下命令,但它不允许完全的外部联接:

SELECT COALESCE(t0.date, t1.date, t2.date, t3.date) AS date,
       COALESCE(t0.hits1, 0) AS hits0,
       COALESCE(t1.hits2, 0) AS hits1,
       COALESCE(t2.hits3, 0) AS hits2
       COALESCE(t3.hits3, 0) AS hits3
FROM t0
FULL OUTER JOIN t1 ON t0.date = t1.date
FULL OUTER JOIN t2 ON COALESCE(t0.date, t1.date) = t2.date;
FULL OUTER JOIN t3 ON COALESCE(t0.date, t1.date, t2.date) = t3.date;

我如何在MySQL中做到这一点?

我知道如何对两个表这样做,例如,按照this example,我可以做:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.id IS NULL

不是:

SELECT * FROM t1 FULL OUTER JOIN t2
ON t1.id = t2.id

但是我该如何做我的第一个例子呢?我得出的以下结论似乎是错误的:

SELECT COALESCE(t0.date, t1.date, t2.date, t3.date) AS date,
        COALESCE(t0.hits1, 0) AS hits0,
        COALESCE(t1.hits2, 0) AS hits1,
        COALESCE(t2.hits3, 0) AS hits2,
        COALESCE(t3.hits3, 0) AS hits3
FROM t0
LEFT JOIN t1 ON t0.date = t1.date
LEFT JOIN t2 ON COALESCE(t0.date, t1.date) = t2.date
LEFT JOIN t3 ON COALESCE(t0.date, t1.date, t2.date) = t3.date
UNION ALL
SELECT COALESCE(t0.date, t1.date, t2.date, t3.date) AS date,
        COALESCE(t0.hits1, 0) AS hits0,
        COALESCE(t1.hits2, 0) AS hits1,
        COALESCE(t2.hits3, 0) AS hits2,
        COALESCE(t3.hits3, 0) AS hits3
FROM t1
RIGHT JOIN t0 ON t0.date = t1.date
RIGHT JOIN t2 ON COALESCE(t0.date, t1.date) = t2.date
RIGHT JOIN t3 ON COALESCE(t0.date, t1.date, t2.date) = t3.date
WHERE t0.date IS NULL
AND t2.date IS NULL
AND t3.date IS NULL

因为下面这一点似乎太严格了:

WHERE t0.date IS NULL
AND t2.date IS NULL
AND t3.date IS NULL

推荐答案

对于你的情况,这可能是一个可行的替代方法,也可能不是.您可以首先构建所有日期的完全联合,然后将连接保留到每个表:

SELECT
    d.date,
    COALESCE(t0.hits1, 0) AS hits0,
    COALESCE(t1.hits2, 0) AS hits1,
    COALESCE(t2.hits3, 0) AS hits2
    COALESCE(t3.hits3, 0) AS hits3
FROM (
    SELECT date FROM t0 UNION
    SELECT date FROM t1 UNION
    SELECT date FROM t2 UNION
    SELECT date FROM t3
) d
LEFT JOIN t0 ON d.date = t0.date
LEFT JOIN t1 ON d.date = t1.date
LEFT JOIN t2 ON d.date = t2.date
LEFT JOIN t3 ON d.date = t3.date;

或者可能用递归CTE替换所有日期的并集:

WITH RECURSIVE d (date) AS (
    SELECT '2023-01-01'
    UNION ALL
    SELECT date + INTERVAL 1 DAY FROM d
    WHERE date + INTERVAL 1 DAY <= CURRENT_DATE
)
SELECT d.date,
       COALESCE(t0.hits1, 0) AS hits0,
       COALESCE(t1.hits2, 0) AS hits1,
       COALESCE(t2.hits3, 0) AS hits2
       COALESCE(t3.hits3, 0) AS hits3
FROM d
LEFT JOIN t0 ON d.date = t0.date
LEFT JOIN t1 ON d.date = t1.date
LEFT JOIN t2 ON d.date = t2.date
LEFT JOIN t3 ON d.date = t3.date;

您还可以添加一个HAVING子句来删除没有匹配的日期:

HAVING hits0 OR hits1 OR hits2 OR hits3

Mysql相关问答推荐

拒绝非超级用户访问停靠的MariaDB(超级用户工作)

如何防止程序中计数器出错

MySQL多次联接同一个表使计数变得奇怪

亚马逊RDS MySQL-无法';t执行';使用读取锁定刷新表';

在 .NET 6 中使用 Dapper Framework 未能成功连接到 MySql

任何值的 SQL WHERE 子句?

将 AVG 与 HAVING 结合使用

在 MySQL 中跨日期和位置计算和排序实体的共现

为什么没有创建此触发器?

MySQL 根据另一列中的值更改空值

为什么这个查询需要超过 5 秒才能运行?

查询以从约会表中获取可用空档

如何在 MySQL 中搜索多个列?

Ansible 幂等 MySQL 安装 Playbook

org.hibernate.InstantiationException:没有实体的默认构造函数::principal.Cliente

MySQL嵌套 Select 查询?

如何从 MySQL Workbench 中的图表生成 SQL 脚本?

MySQL 实用程序 - ~/.my.cnf 选项文件

应该使用什么列类型将序列化数据存储在 mysql 数据库中?

cron 启动的 mysqldump 和密码安全