如何将两个SQL查询合并为一个?

问题描述 投票:0回答:1

我有两个查询可以生成我想要的结果。一个查询返回 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 有什么问题?

sql join
1个回答
0
投票

我缺少正确的表定义,因为我不知道为表设置的约束是什么。但是,据我了解您如何使用这些表格:

  • 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
    相关的表,您可以根据它们的聚合构造所需的附加数据。

鉴于这个假设是正确的,您可以尝试以下操作:

  1. 与您的方法类似,缺点是它意味着对
    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之间连接的唯一条件,并在子查询中省略它主查询的选择

  1. 另一种无需查询两次的方法
    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 时,除一个之外的所有表)。不是这种情况)。考虑到表的大小,我不确定选择是否存在显着的性能差异。

希望对您有帮助,祝您工作顺利

© www.soinside.com 2019 - 2024. All rights reserved.