具有4个子查询的SQL查询

时间:2018-06-24 21:29:48

标签: sql sql-server subquery sql-server-2014

为什么这些子查询方法之一有效,而另一方法无效?有什么更有效的方法来构造此数据?

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

我首先尝试查询A,但3个小时后仍在处理。查询B几乎立即生效。

实体表中有255行,时间序列表中有〜150000行。运行SQL Server2014。

查询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

1 个答案:

答案 0 :(得分:3)

您的第一个查询会导致多对多连接:将表#1中具有PROPNUM n的每一行连接到表#2中具有相同PROPNUM n的每一行,依此类推。

但是当您使用不同的WHERE条件多次连接同一张表时,可以将其替换为条件聚合

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