sql - 如何基于一列连接多个表的结果(通过 UNION ALL)
问题描述
好吧,我编写的 SQL 语句运行良好,但我想让它不那么笨重,并且只使用一个“ACCEPTANCE_DATE”,因为它在所有表中都是相同的。
我正在尝试使用 UNION ALL 语句加入多个表的结果。下面的例子工作得很好。
SEL COUNT(*)FROM
MY_DATABASE.HUMAN_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09'
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.FINANCIAL_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09'
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09';
所有表都有相同类型的列,例如每个表都有一个名为“ACCEPTANCE_DATE”的列。我得到的结果是正确的。尽管如此,我在一个查询中组合了很多表(使用 UNION ALL)并且想知道是否有办法转换这个查询,所以我不必在每个选择语句中更新 ACCEPTANCE_DATE='2015-08-09' . 理想情况下,我只想定义一次,尤其是当我使用超过 30 个 UNION ALL 子句时,例如
SEL * FROM
(SEL COUNT(*)FROM
MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES) AS T1
WHERE ACCEPTANCE_DATE='2015-08-09';
下面的语句获取数据。
SEL COUNT(*)FROM
MY_DATABASE.HUMAN_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09'
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.FINANCIAL_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09'
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES
WHERE ACCEPTANCE_DATE='2015-08-09';
如上所述,我希望它类似于以下内容:
SEL * FROM
(SEL COUNT(*)FROM
MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL COUNT(*)FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES) AS T1
WHERE ACCEPTANCE_DATE='2015-08-09';
解决方案
也许这就是您正在寻找的:
SEL COUNT(*) FROM
(SEL ACCEPTANCE_DATE, 1 AS ORIGIN FROM
MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 2 AS ORIGIN FROM
MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 3 AS ORIGIN FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES) AS T1
WHERE ACCEPTANCE_DATE='2015-08-09'
GROUP BY ORIGIN;
您甚至可以给 ORIGIN 一些更有意义的名称并在之后显示它们:
SEL ORIGIN, COUNT(*) FROM
(SEL ACCEPTANCE_DATE, 'HUMAN' AS ORIGIN FROM
MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 'FINANCIAL' AS ORIGIN FROM
MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 'INFRASTRUCTURE' AS ORIGIN FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES) AS T1
WHERE ACCEPTANCE_DATE='2015-08-09'
GROUP BY ORIGIN;
这导致两列。现在,它仍然没有解决第三个值不显示的问题,但是这样您就知道哪些值丢失了,并且可以轻松区分哪些应该是零。如果这对您来说还不够,那么代码会变得更糟糕。以后可能会想办法解决。
为了解决空表丢失条目的问题,我想到了两种可能的解决方案。选择取决于操作是否只执行一次,或者这是重复发生的操作还是仅执行一次事件。如果您计划多次执行此操作,那么在数据库上创建一个包含所有原始表名称(或一些快捷方式,您会明白的)的表可能是个好主意。对于这个最小的例子,让我们考虑这样一个存在于名称 SOURCE_TABLES 下的东西:
SELECT RESOURCE FROM SOURCE_TABLES
/*
RESOURCE:
HUMAN
FINANCIAL
INFRASTRUCTURE
*/
在这种情况下,之前提供的脚本只需要稍作修改:
SEL ST.RESOURCE, COUNT(T1.ACCEPTANCE_DATE) FROM SOURCE_TABLES ST
LEFT JOIN (SEL ACCEPTANCE_DATE, 'HUMAN' AS ORIGIN FROM
MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 'FINANCIAL' AS ORIGIN FROM
MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 'INFRASTRUCTURE' AS ORIGIN FROM
MY_DATABASE.INFRASTRUCTURE_RESOURCES) AS T1
ON ST.RESOURCE = T1.ORIGIN
WHERE ACCEPTANCE_DATE='2015-08-09'
GROUP BY ST.RESOURCE;
在这里,通过使用 LEFT JOIN,您可以确保表中的每个条目都存在于输出中,即使在 T1 中没有具有指定来源的行。COUNT(T1.ACCEPTANCE_DATE) 利用了 NULL 不累加到计数器的事实。
现在,如果出于某种原因您不喜欢创建表的想法(您不能在数据库上创建对象或者单个操作太麻烦),您可以坚持使用更容易的数字的想法即时生成。下面的解决方案利用了与上面相同的想法,但在读取的表数量方面更加灵活,并且显然不需要您创建额外的表。考虑到您提到了 30 张桌子,这可能是一个更好的选择。有人可以争辩说它的可读性较差:
WITH numbers AS (
SEL 1 AS number
UNION ALL
SEL number + 1 FROM numbers WHERE number + 1 <= 3 -- Change 3 to the number of sourcing tables
), input_merged AS ( -- if we already use the WITH clause we can do so for merging input. It's more readable
SEL ACCEPTANCE_DATE, 1 AS ORIGIN FROM MY_DATABASE.HUMAN_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 2 AS ORIGIN FROM MY_DATABASE.FINANCIAL_RESOURCES
UNION ALL
SEL ACCEPTANCE_DATE, 3 AS ORIGIN FROM MY_DATABASE.INFRASTRUCTURE_RESOURCES
-- add further sources accordingly...
)
SEL COUNT(ACCEPTANCE_DATE) FROM numbers n
LEFT JOIN input_merged im ON n.number = im.ORIGIN
WHERE ACCEPTANCE_DATE='2015-08-09'
GROUP BY n.number;
这应该会产生第一个询问和期望的输出。
至于 WITH 语句中的数字部分,您可能需要参考this,请注意,在此解决方案中,我使用 WITH 也像 Christoph 那样合并输入。如果您使用 ORACLE 数据库,则使用 CONNECT BY LEVEL 可能是创建数字序列的更好选择。
希望现在你可以实现你想要的!
推荐阅读
- python - 用循环替换字符串中的单词
- python - 根据条件创建新列会出错
- asp.net-core - Blazor 中的项目,控制器无法正常工作并且程序文件错误很多
- python - 导入 pandas 退出 python 控制台
- java - 根据索引从排序的升序数组生成输出
- linker - 如何找到 linux elf 可执行文件在哪里找到并满足外部引用
- cmake - 接口库的自定义属性
- r - 如何提取第二次出现的重复主题 ID 或第一次(如果不重复)?
- python - 一次在python中打开列表列表中的所有文件
- docker - Traefik v2 - 将唯一跟踪 ID 添加到标头