SQL 包含 4 个子查询的查询

SQL Query with 4 subqueries

为什么这些子查询方法中的一种有效而另一种无效?构建这些数据的更有效方法是什么?

我有一个实体 table,然后是一个时间序列 table,对应于那些具有不同类型生产数据的实体。我正在尝试获取每个生产流的第一个日期。

我首先尝试了查询 A,3 小时后它仍在运行。查询 B 几乎立即生效。

实体 table 中有 255 行,时间序列 table 中有约 150000 行。 运行 SQL 服务器 2014。

查询 A:(无效)

select 
    main.PROPNUM
    ,min(sub_fluid.d_date) as [first_fluid]
    ,min(sub_hc.d_date) as [first_hydrocarbon]
    ,min(sub_oil.d_date) as [first_oil]
    ,min(sub_gas.d_date) as [first_gas]
from daily_production as main

left join
    (
    select
        PROPNUM
        ,D_DATE
        ,(oil+gas+water) as fluid
    from daily_production
    where (oil+gas+water) > 0
    )  as sub_fluid
on main.PROPNUM = sub_fluid.PROPNUM

left join
    (
    select
        PROPNUM
        ,D_DATE
        ,(oil+gas) as hydrocarbon
    from daily_production
    where (oil+gas) > 0
    )  as sub_hc

on main.PROPNUM = sub_hc.PROPNUM

left join
    (
    select
        PROPNUM
        ,D_DATE
        ,oil
    from daily_production
    where (oil) > 0
    )  as sub_oil
on main.PROPNUM = sub_oil.PROPNUM

left join
    (
    select
        PROPNUM
        ,D_DATE
        ,gas
    from daily_production
    where (gas) > 0
    )  as sub_gas
on main.PROPNUM = sub_gas.PROPNUM

group by main.PROPNUM

查询 B:(效果很好)

select
    daily_production.propnum
    ,first_fluid.first_fluid
    ,first_hydrocarbon.first_hydrocarbon
    ,first_oil.first_oil
    ,first_gas.first_gas

from daily_production

left join

(select 
    sub_fluid.PROPNUM
    ,min(sub_fluid.d_date) as [first_fluid]
from
    (
    select
        PROPNUM
        ,D_DATE
        ,(oil+gas+water) as fluid
    from daily_production
    where (oil+gas+water) > 0
    )  as sub_fluid
group by PROPNUM) as first_fluid

on daily_production.PROPNUM = first_fluid.PROPNUM

left join

(select 
    sub_hc.PROPNUM
    ,min(sub_hc.d_date) as [first_hydrocarbon]
from
    (
    select
        PROPNUM
        ,D_DATE
        ,(oil+gas) as hydrocarbon
    from daily_production
    where (oil+gas) > 0
    )  as sub_hc
group by PROPNUM) as first_hydrocarbon

on daily_production.PROPNUM = first_hydrocarbon.PROPNUM

left join

(select 
    sub_oil.PROPNUM
    ,min(sub_oil.d_date) as [first_oil]
from
    (
    select
        PROPNUM
        ,D_DATE
        ,(oil) 
    from daily_production
    where (oil) > 0
    )  as sub_oil
group by PROPNUM) as first_oil

on daily_production.PROPNUM = first_oil.PROPNUM

left join

(select 
    sub_gas.PROPNUM
    ,min(sub_gas.d_date) as [first_gas]
from
    (
    select
        PROPNUM
        ,D_DATE
        ,(gas) 
    from daily_production
    where (gas) > 0
    )  as sub_gas
group by PROPNUM) as first_gas

on daily_production.PROPNUM = first_gas.PROPNUM

group by daily_production.PROPNUM, first_fluid.first_fluid, first_hydrocarbon.first_hydrocarbon, first_oil.first_oil, first_gas.first_gas

您的第一个查询导致多对多连接:您将 table #1 中具有 PROPNUM n 的每一行连接到 table #2 中具有相同 PROPNUM n 的每一行,并且等等。

但是当您使用不同的 WHERE 条件多次加入相同的 table 时,您可以将其替换为 条件聚合:

select 
    PROPNUM
    ,min(case when (oil+gas+water) > 0 then d_date end) as [first_fluid]
    ,min(case when (oil+gas) > 0 then d_date end) as [first_hydrocarbon]
    ,min(case when (oil) > 0 then d_date end) as [first_oil]
    ,min(case when (gas) > 0 then d_date end) as [first_gas]
from daily_production
group by PROPNUM