左边的前1加入SubQuery

时间:2009-01-30 06:56:41

标签: sql sql-server

我正试图带一个人,并显示他们目前的保险以及他们以前的保险。我想有人可以说我试图激发我对客户或人的看法。由于我的左连接子查询中存在多个记录,我遇到了一个问题,我正在收到多条记录。我希望通过在子查询中添加“TOP 1”来解决这个问题,但实际上并没有返回任何内容......

有什么想法吗?

    SELECT 
    p.person_id AS 'MIRID'
    , p.firstname AS 'FIRST'
    , p.lastname AS 'LAST'
    , pg.name AS 'GROUP'
    , e.name AS 'AOR'
    , p.leaddate AS 'CONTACT DATE'
    , [dbo].[GetPICampaignDisp](p.person_id, '2009') AS 'PI - 2009'
    , [dbo].[GetPICampaignDisp](p.person_id, '2008') AS 'PI - 2008'
    , [dbo].[GetPICampaignDisp](p.person_id, '2007') AS 'PI - 2007'
    , a_disp.name AS 'CURR DISP'
    , a_ins.name AS 'CURR INS'
    , a_prodtype.name AS 'CURR INS TYPE'
    , a_t.date AS 'CURR INS APP DATE'
    , a_t.effdate AS 'CURR INS EFF DATE' 
    , b_disp.name AS 'PREV DISP'
    , b_ins.name AS 'PREV INS'
    , b_prodtype.name AS 'PREV INS TYPE'
    , b_t.date AS 'PREV INS APP DATE'
    , b_t.effdate AS 'PREV INS EFF DATE'
    , b_t.termdate AS 'PREV INS TERM DATE'
FROM 
    [person] p
LEFT OUTER JOIN 
    [employee] e
ON 
    e.employee_id = p.agentofrecord_id
INNER JOIN 
    [dbo].[person_physician] pp
ON 
    p.person_id = pp.person_id
INNER JOIN 
    [dbo].[physician] ph
ON
    ph.physician_id = pp.physician_id
INNER JOIN
    [dbo].[clinic] c
ON 
    c.clinic_id = ph.clinic_id
INNER JOIN
    [dbo].[d_Physgroup] pg
ON
    pg.d_physgroup_id = c.physgroup_id
LEFT OUTER JOIN 
    (
        SELECT
            tr1.*
        FROM 
            [transaction] tr1
        LEFT OUTER JOIN 
            [d_vendor] ins1
        ON 
            ins1.d_vendor_id = tr1.d_vendor_id
        LEFT OUTER JOIN 
            [d_product_type] prodtype1
        ON 
            prodtype1.d_product_type_id = tr1.d_product_type_id
        LEFT OUTER JOIN 
            [d_commission_type] ctype1
        ON 
            ctype1.d_commission_type_id = tr1.d_commission_type_id
        WHERE
            prodtype1.name <> 'Medicare Part D'
            AND tr1.termdate IS NULL
    ) AS a_t
ON
    a_t.person_id = p.person_id
LEFT OUTER JOIN 
    [d_vendor] a_ins
ON 
    a_ins.d_vendor_id = a_t.d_vendor_id
LEFT OUTER JOIN 
    [d_product_type] a_prodtype
ON 
    a_prodtype.d_product_type_id = a_t.d_product_type_id
LEFT OUTER JOIN 
    [d_commission_type] a_ctype
ON 
    a_ctype.d_commission_type_id = a_t.d_commission_type_id
LEFT OUTER JOIN
    [d_disposition] a_disp
ON
    a_disp.d_disposition_id = a_t.d_disposition_id
LEFT OUTER JOIN 
    (
        SELECT
            tr2.*
        FROM 
            [transaction] tr2
        LEFT OUTER JOIN 
            [d_vendor] ins2
        ON 
            ins2.d_vendor_id = tr2.d_vendor_id
        LEFT OUTER JOIN 
            [d_product_type] prodtype2
        ON 
            prodtype2.d_product_type_id = tr2.d_product_type_id
        LEFT OUTER JOIN 
            [d_commission_type] ctype2
        ON 
            ctype2.d_commission_type_id = tr2.d_commission_type_id
        WHERE
            prodtype2.name <> 'Medicare Part D'
            AND tr2.termdate IS NOT NULL
    ) AS b_t
ON
    b_t.person_id = p.person_id
LEFT OUTER JOIN 
    [d_vendor] b_ins
ON 
    b_ins.d_vendor_id = b_t.d_vendor_id
LEFT OUTER JOIN 
    [d_product_type] b_prodtype
ON 
    b_prodtype.d_product_type_id = b_t.d_product_type_id
LEFT OUTER JOIN 
    [d_commission_type] b_ctype
ON 
    b_ctype.d_commission_type_id = b_t.d_commission_type_id
LEFT OUTER JOIN
    [d_disposition] b_disp
ON
    b_disp.d_disposition_id = b_t.d_disposition_id
WHERE
    pg.d_physgroup_id = @PhysGroupID

5 个答案:

答案 0 :(得分:16)

在Sql server 2005中,您可以使用OUTER APPLY

SELECT p.person_id, s.e.employee_id
FROM person p
OUTER APPLY (SELECT TOP 1 *
             FROM Employee
         WHERE /*JOINCONDITION*/
         ORDER BY /*Something*/ DESC) s

http://technet.microsoft.com/en-us/library/ms175156.aspx

答案 1 :(得分:7)

我通常使用的模式是:

  

选择任何
  来自人   LEFT JOIN子表AS s1
     ON s1.personid = person.personid

     

...

     

不存在的内容
  (SELECT 1 FROM subtable
       在哪里personid = person.personid
           AND orderbydate&gt; s1.orderbydate   )

这避免了TOP 1条款,可能会让它更清晰。

顺便说一下,我喜欢你把这个查询放在一起的方式,除非我省略括号,假设你已经合理地命名了表和列;你甚至可以通过列出tr1和tr2的列而不是“tr1。*”和“tr2。*”来获得一些性能(但至少是优雅)。

答案 2 :(得分:1)

感谢所有的反馈和想法...

用最简单的术语来说,我有一个人员表来存储姓名,电子邮件等联系信息。我有另一个存储交易的表。每笔交易实际上都是一份保险单,其中包含有关提供商,产品类型,产品名称等的信息。

我想避免向用户提供重复的人员记录,因为这会导致他们在运行邮件合并等之前查找重复项。当有超过1个尚未终止的事务时,我会收到重复项有超过1个已终止的交易。

其他人建议我考虑使用光标抓取我的不同联系人记录,然后执行子选择以获取当前和以前的保险信息。我不知道我是不是想走这条路。

答案 3 :(得分:0)

很难理解你的问题所以首先我会把它扔出去:将SELECT改为SELECT DISTINCT会做你想做的吗?

否则,让我直截了当,你试图获得客户当前的保险和以前的保险,但他们之前可能会有很多保险,记录在[交易]表中?我看了你的SQL很长一段时间,但无法弄清楚这一切意味着什么,所以请你把它减少到只有必要的部分?然后我会考虑更多。听起来我觉得你需要一个GROUP BY,但我还是无法解决它。

答案 4 :(得分:0)

无法花时间挖掘所有SQL(这是一个什么样的野兽!),这是一个可以让事情更容易处理的想法:

select 
 p.person_id, p.name <and other person columns>,
 (select <current policy columns>
  from pol <and other tables for policy>
  where pol.<columns for join> = p.person_id
  and <restrictions for current policy>),
 (select <previous policy columns>
  from pol <and other tables for policy>
  where pol.<columns for join> = p.person_id
  and <restrictions for previouspolicy>),
 <other columns>
from person p <and "directly related" tables>

通过将不同的部分分成它们自己的子选择,这使得语句更容易阅读,并且还可以更容易地添加“Top 1”而不影响语句的其余部分。希望有所帮助。