使用返回null的子查询进行查询

时间:2013-04-15 19:13:46

标签: sql oracle subquery left-join

我有一个查询来提取有关用户的信息。用户可以没有,一个或多个电话号码。我想要做的是将用户最新的电话号码(由序列号确定)加入到包含其他基本人口统计数据的查询中。我面临的问题是,如果我的子查询返回null,则用户不会在我的查询中显示。如何处理子查询中的空值以便仍然返回这些行?

SELECT  SPRIDEN.SPRIDEN_ID AS Student_ID ,
        saradap.SARADAP_APST_CODE ,
        saradap.SARADAP_PIDM ,
        spriden.spriden_first_name ,
        spriden.spriden_last_name ,
        saradap.saradap_program_1 ,
        spraddr.SPRADDR_STREET_LINE1 ,
        spraddr.spraddr_city ,
        spraddr.spraddr_zip ,
        spraddr.spraddr_stat_code ,
        saradap.SARADAP_APPL_DATE ,
        'Individual' AS Account_Name ,
        saradap.SARADAP_CAMP_CODE ,
        CONCAT(sprtele_phone_area, sprtele_phone_number) "Phone" ,
        sprtele_tele_code ,
        sorcont_ctyp_code ,
        sorcont_contact_date ,
        sorcont.sorcont_activity_date
FROM    saradap
        LEFT JOIN spriden ON saradap.saradap_pidm = spriden_pidm
        LEFT JOIN spraddr ON saradap.saradap_pidm = spraddr.spraddr_pidm
        LEFT  JOIN sprtele ON saradap.saradap_pidm = sprtele.sprtele_pidm
        LEFT JOIN sorcont ON saradap.saradap_pidm = sorcont.sorcont_pidm
WHERE   spriden.spriden_change_ind IS NULL
        AND ( saradap.SARADAP_CAMP_CODE = 'D'
              OR saradap.SARADAP_CAMP_CODE = 'JD'
            )
        AND saradap.saradap_appl_date > SYSDATE - 15
        AND spraddr.spraddr_seqno = ( SELECT    MAX(spraddr.spraddr_seqno)
                                      FROM      spraddr
                                      WHERE     saradap.SARADAP_PIDM = spraddr.spraddr_pidm
                                    )
        AND sprtele_seqno = ( SELECT    MAX(SPRTELE_SEQNO)
                              FROM      SATURN.SPRTELE
                              WHERE     sprtele_pidm = saradap.saradap_pidm
                            )

3 个答案:

答案 0 :(得分:1)

我会将逻辑移动到from子句中的子查询中。使用分析函数获取所需的电话号码和地址,同时省去子查询:

SELECT . . .
FROM    saradap
        LEFT JOIN spriden
        ON saradap.saradap_pidm = spriden_pidm
        LEFT JOIN (select s.*, row_number() over (partition by spraddr_pidm order by spraddr_seqno desc) as seqnum
                   from spraddr
                  ) spraddr
        ON saradap.saradap_pidm = spraddr.spraddr_pidm and seqnum = 1
        LEFT JOIN (select s.*, row_number() over (partition by sprtele_pidm order by sprtele_seqno desc) as seqnum
                   from sprtele
                  ) sprtele
        ON saradap.saradap_pidm = sprtele.sprtele_pidm and seqnum = 1
        LEFT JOIN sorcont
        ON saradap.saradap_pidm = sorcont.sorcont_pidm
WHERE   spriden.spriden_change_ind IS NULL
        AND ( saradap.SARADAP_CAMP_CODE = 'D'
              OR saradap.SARADAP_CAMP_CODE = 'JD'
            )
        AND saradap.saradap_appl_date > SYSDATE - 15

答案 1 :(得分:1)

Sebas让我在这里完成了一个完整的查询。我最终不得不使用CTE。作为旁注,我是一个新的stackoverflow用户,如何帮助我得到答案的答案呢?

with
tel(sprtele_pidm, mx) as ( SELECT    sprtele_pidm, MAX(SPRTELE_SEQNO) as "mx"
                    FROM      SATURN.SPRTELE where saturn.sprtele.sprtele_tele_code ='CU'
                    GROUP BY sprtele_pidm
                  ) 
SELECT SPRIDEN.SPRIDEN_ID AS Student_ID,
saradap.SARADAP_APST_CODE,
saradap.SARADAP_PIDM,
spriden.spriden_first_name,
spriden.spriden_last_name,
saradap.saradap_program_1,
spraddr.SPRADDR_STREET_LINE1,
spraddr.spraddr_city,
spraddr.spraddr_zip,
spraddr.spraddr_stat_code,
null as STAVAPDC_DESC,
saradap.SARADAP_APPL_DATE,
'Null' AS remove_reason,
'Individual'         AS Account_Name,
saradap.SARADAP_CAMP_CODE,
CONCAT(sprtele_phone_area,
sprtele_phone_number) "Phone",
sprtele_tele_code,
sorcont_ctyp_code,
sorcont_contact_date,
sorcont.sorcont_activity_date
FROM saradap
left join spriden on saradap.saradap_pidm            = spriden_pidm
left join spraddr on  saradap.saradap_pidm      = spraddr.spraddr_pidm
left join tel on saradap.saradap_pidm = tel.sprtele_pidm
left join sprtele ON saradap.saradap_pidm=sprtele.sprtele_pidm and sprtele.sprtele_pidm = tel.sprtele_pidm and sprtele.sprtele_seqno=tel.mx and sprtele.sprtele_tele_code = 'CU'
left join sorcont ON saradap.saradap_pidm = sorcont.sorcont_pidm
WHERE
spriden.spriden_change_ind     IS NULL
AND (saradap.SARADAP_CAMP_CODE       = 'D' or saradap.SARADAP_CAMP_CODE       = 'JD')
AND saradap.saradap_appl_date > SYSDATE - 7
AND spraddr.spraddr_seqno     =
(SELECT MAX(spraddr.spraddr_seqno)
FROM spraddr
WHERE saradap.SARADAP_PIDM    = spraddr.spraddr_pidm
AND spraddr.spraddr_atyp_code = 'CU'
)
AND spraddr.spraddr_atyp_code = 'CU'

答案 2 :(得分:0)

测试子查询是否为NULL并返回一个非常大的数字或0

查看类似的订单答案:SQL Server ORDER BY date and nulls last

( CASE (SELECT    MAX(spraddr.spraddr_seqno)
                                  FROM      spraddr
                                  WHERE     saradap.SARADAP_PIDM = spraddr.spraddr_pidm)
    IS NULL
    THEN 1
    ELSE 0
    END