我有两个查询可以生成我想要的结果。一个查询返回 3 列,另一个查询返回 4 列。但是,我不知道如何使这两个查询生成一个表结果。
我的第一个查询是:
Select
dt_facility.facility_code, dt_facility.facility_name,
count(dt_result.cas_rn) as 'No_of_result'
from
dt_facility
left join
dt_result on dt_facility.facility_id = dt_result.facility_id
group by
dt_facility.facility_code, dt_facility.facility_name;
此查询会生成设施代码、名称以及数据库中的结果总数。
第二个查询是:
Select
dt_facility.facility_code, dt_facility.facility_name,
min(dt_sample.sample_date) as 'sample_start_date',
max(dt_sample.sample_date) as 'sample_end_date'
from
dt_facility
left join
dt_sample on dt_facility.facility_id = dt_sample.facility_id
group by
dt_facility.facility_code, dt_facility.facility_name;
第二个查询显示设施代码、名称、最后开始日期和最早开始日期。
他们都产生了我想要的结果;但是,我不知道如何将它们放在一起,所以我可以看到一个表格,其中包含设施代码、设施名称、结果总数、样本的最小日期和样本的最大日期。
我尝试做
cross join
,但它没有返回我想要的结果:
select
*
from
(select
dt_facility.facility_code, dt_facility.facility_name,
count(*) as 'No_of_result'
from
dt_facility
left join
dt_result on dt_facility.facility_id = dt_result.facility_id
group by
dt_result.facility_id, dt_facility.facility_code, dt_facility.facility_name) A
cross join
(select
dt_facility.facility_code, dt_facility.facility_name,
min(dt_sample.sample_date) as 'sample_start_date',
max(dt_sample.sample_date) as 'sample_end_date'
from
dt_facility
left join
dt_sample on dt_facility.facility_id = dt_sample.facility_id
group by
dt_facility.facility_code, dt_facility.facility_name) B
我的 SQL 有什么问题?
我缺少正确的表定义,因为我不知道为表设置的约束是什么。但是,据我了解您如何使用这些表格:
dt_facility.facility_id
是您的主键,在整个表中是唯一的dt_facility.facility_code
和 dt_facility.facility_name
,尽管它们本身不是 PK,但它们可以作为单个复合主键(不能有重复对)或作为两个单独的主键。 (在这种情况下,如果可能的话,我建议删除 facility_id
并使用 facility_code
或 (facility_code, facility_name)
作为主键)dt_result
和 dt_sample
是通过多对一关系与 dt_facility
相关的表,您可以根据它们的聚合构造所需的附加数据。鉴于这个假设是正确的,您可以尝试以下操作:
dt_facility
表进行两次表查找:SELECT * FROM (
SELECT
dt_facility.facility_code,
dt_facility.facility_name,
count(*) as 'No_of_result'
FROM dt_facility
LEFT JOIN dt_result ON dt_facility.facility_id = dt_result.facility_id
GROUP BY dt_result.facility_id, dt_facility.facility_code, dt_facility.facility_name
) A
LEFT JOIN (
SELECT
dt_facility.facility_code,
dt_facility.facility_name,
min(dt_sample.sample_date) as 'sample_start_date',
max(dt_sample.sample_date) as 'sample_end_date'
FROM dt_facility
LEFT JOIN dt_sample ON dt_facility.facility_id = dt_sample.facility_id
GROUP BY dt_facility.facility_code, dt_facility.facility_name
) B on A.facility_code = B.facility_code AND A.facility_name = B.facility_name
虽然您的交叉连接方法将组合两个查询结果之间的所有可能组合 (
resulting rows will be count(A) * count(B)
),但左连接将匹配具有相同对的结果 (facility_code and facility_name)
facility_code
是唯一的,您可以跳过左连接的 facility_name
条件中的 ON
检查(facility_code, facility_name)
对在dt_facility
表中NOT是唯一的,您可以在子查询中包含
facility_id
,将其用作A和B之间连接的唯一条件,并在子查询中省略它主查询的选择dt_facility
(我认为这种方法会更便宜,但你应该将它们与ANALYZE
进行比较才能确定):SELECT
f.facility_code,
f.facility_name,
COUNT(r.cas_rn) AS "No_of_result",
MIN(s.sample_start_date),
MAX(s.sample_end_date)
FROM dt_facility f
LEFT JOIN dt_result r ON f.facility_id = r.facility_id
LEFT JOIN (SELECT
s1.facility_id,
MIN(s1.sample_date) as "sample_start_date",
MAX(s1.sample_date) as "sample_end_date"
FROM dt_sample
GROUP BY s1.facility_id
) s ON s.facility_id = f.facility_id
GROUP BY f.facility_code, f.facility_name;
对第二个 JOIN 使用子查询可以避免同一个给定
dt_sample
具有多个 dt_result
和 dt_facility
的情况,在这种情况下,简单的 JOIN 将导致聚合函数计算两个的重复行表。我喜欢考虑这个问题,就好像同一查询中的多个联接会导致联接表之间的交叉联接。在您的情况下,最小和最大日期不会受到影响,但结果值的计数将乘以每个dt_facility
的样本数量。在子查询中聚合 JOINed 表之一(而不是主查询)的结果可确保仅向每个 s
行提供一行 f
,从而避免此问题。
根据查询结果,您应用子查询的表(样本或结果)是不明确的,您只需将其应用于其中之一(当使用两个以上 JOIN 时,除一个之外的所有表)。不是这种情况)。考虑到表的大小,我不确定选择是否存在显着的性能差异。
希望对您有帮助,祝您工作顺利