【问题标题】:Sybase SQL - Remove "semi-duplicates" from query resultsSybase SQL - 从查询结果中删除“半重复”
【发布时间】:2013-03-21 15:50:04
【问题描述】:

我有一个查询使用两个SELECT 语句,它们使用UNION ALL 组合在一起。这两个语句都从相似的表中提取数据以填充查询结果。我正在尝试从查询中删除“半重复”行,但这样做时遇到问题。

我的查询如下:

    SELECT DISTINCT * 
FROM
    (
    SELECT
        TeamNum = CASE 
                WHEN T.TeamName = 'Alpha Team'
                    THEN '1'
                WHEN T.TeamName IN ('Bravo Team', 'Charlie Team')
                    THEN '2'
                WHEN T.TeamName = 'Delta Team'
                    THEN '3'
                ELSE '<Undefined>'
                END,
        P.PatientLastName AS LastName,
        P.PatientFirstName AS FirstName,
        R.PrimaryCity AS City,
        ReimbursorName = CASE
                WHEN RE.ReimbursorDescription = 'Medicare'
                    Then 'R1'
                WHEN RE.ReimbursorDescription = 'Medicaid'
                    Then 'R2'
                ELSE 'R3'
                END,
        P.PatientID AS PatientID
    FROM 
        PatReferrals PR LEFT JOIN Patient P ON PR.PatientID = P.PatientID,
        Patient P LEFT OUTER JOIN Rolodex R ON P.RolodexID = R.RolodexID,
        PatReferrals PR LEFT OUTER JOIN PatReimbursors PRE ON PR.PatientID = PRE.PatientID,
        PatReimbursors PRE LEFT OUTER JOIN Reimbursors RE ON PRE.ReimbursorID = RE.ReimbursorID,
        PatReferrals PR FULL OUTER JOIN Teams T ON PR.TeamID = T.TeamID,
    WHERE 
        PR.ReferralDate BETWEEN GETDATE()-4 AND GETDATE()-1
        AND PR.Status <> 'R' 
        AND PRE.CoveragePriority = '1'
        AND PRE.ExpirationDate IS NULL 

    UNION ALL

    SELECT
        TeamNum = CASE 
                WHEN T.TeamName = 'Alpha Team'
                    THEN '1'
                WHEN T.TeamName IN ('Bravo Team', 'Charlie Team')
                    THEN '2'
                WHEN T.TeamName = 'Delta Team'
                    THEN '3'
                ELSE '<Undefined>'
                END,
        P.PatientLastName AS LastName,
        P.PatientFirstName AS FirstName,
        R.PrimaryCity AS City,
        ReimbursorName = CASE
                WHEN RE.ReimbursorDescription = 'Medicare'
                    Then 'E1'
                WHEN RE.ReimbursorDescription = 'Medicaid'
                    Then 'E2'
                ELSE 'E3'
                END,
        P.PatientID AS PatientID
    FROM 
        PatReferrals PR LEFT JOIN Patient P ON PR.PatientID = P.PatientID,
        Patient P LEFT OUTER JOIN Rolodex R ON P.RolodexID = R.RolodexID,
        PatReferrals PR LEFT OUTER JOIN PatEligibilities PE ON PR.PatientID = PE.PatientID,
        PatEligibilities PE LEFT OUTER JOIN Reimbursors RE ON PE.ReimbursorID = RE.ReimbursorID,
        PatReferrals PR FULL OUTER JOIN Teams T ON PR.TeamID = T.TeamID,
    WHERE 
        PR.ReferralDate BETWEEN GETDATE()-4 AND GETDATE()-1
        AND PR.Status <> 'R' 
        AND PE.Status <> 'V'
        AND PE.ApplicationDate BETWEEN DATE(PR.ReferralDate)-5 AND DATE('2100/01/01')
    ) 

AS DUMMYTBL

ORDER BY 
    DUMMYTBL.LastName ASC,
    DUMMYTBL.FirstName ASC

我在运行查询时收到的结果如下:

3   Doe Jane    Town    R1  19874
1   Roe John    City    R3  50016
1   Roe John    City    E1  50016
2   Smith   Jane    Town    E3  33975

一旦从原始查询中引入结果,我需要删除的数据是基于特定条件的重复行。每个人只能列出一次,并且他们必须有一个支付来源(R1、R2、R3、E1、E2、E3)。如果有 R#,则不能为该人列出 E#。如果没有 R#,则必须列出 E#。如我的示例结果所示,第 2 行和第 3 行列出了同一个人,但有两个支付来源(R3 和 E1)。

如何使用我列出的标准让每个人只显示一行?

编辑:修改了 SQL 查询以显示来自 WHERE 子句的原始变量,以便显示查询的更多详细信息。 PatReimbursors 和 PatEligibilities 表具有相似的数据,但为了提取正确的数据,标准不同。

【问题讨论】:

  • TeamNum = T.TeamName,?是不是打错字了?
  • 这真的是一个有效的查询吗? from 子句似乎多次出现相同的别名 - 看起来好像永远无法运行。另外,如果有多个“R”源,哪个优先?
  • @Rachcha - 我缩短了查询的那部分,因为它最初是一个 CASE 语句以从 TeamName 返回数字。 @Mark Ba​​nnister - 是的,这个查询确实有效。

标签: sql sybase duplicate-removal sybase-asa


【解决方案1】:

您的查询没有意义。我将首先消除由,from 子句中生成的隐式笛卡尔积。

我的猜测是 from 子句应该是:

FROM 
    PatReferrals PR LEFT JOIN
    Patient P
    ON PR.PatientID = P.PatientID left outer join
    Rolodex R
    ON P.RolodexID = R.RolodexID left outer join
    PatEligibilities PE
    ON PR.PatientID = PE.PatientID left outer join
    Reimbursors RE
    ON PE.ReimbursorID = RE.ReimbursorID left outer join
    Teams T ON PR.TeamID = T.TeamID

执行此操作后,您可能不需要union allselect distinct。您可以在同一个查询中同时输入报销金额和资格。

【讨论】:

  • PatReferrals 表分叉给 PatReimbursors 和 PatEligibilities。为了让两个值都填充到同一个查询中,必须插入两个相似的 SELECT 语句的 UNION。没有它,我要么从 PatReimbursors 要么从 PatEligibilities 获取数据,但不能同时从两者中获取。
  • 没关系。这可以防止一种类型的笛卡尔积。但是,您通过在from 子句中包含“,”来介绍多个其他人。
【解决方案2】:

使用一个或多个子查询。

应使用以下模式编写整体查询:

 Select Distinct [Person Data]
 From PersonTable
     left Join to otherTable1 -- add outer join for each table you need data from
         On [Conditions that ensure join can generate only one row per person,
               ... and specify which of possibly many rows to get...]

确保条件消除了连接从另一个 [outer] 表中的 person 表中的每个 person 行生成多个行的任何可能性。这可能(并且经常)要求连接条件基于子查询,例如...

 Select Distinct [Person Data]
 From PersonTable p
     left Join to employments e -- add outer join for each table you need data from
         On e.PersonId = p.PersonId 
            and e.HireDate = (Select Max(hiredate) from employments
                              where personId = p.PersonId)

【讨论】:

    【解决方案3】:

    在今天处理了相当长的一段时间后,我找到了解决我遇到的问题的方法。这是有效的解决方案,并提取了我需要的正确信息:

    SELECT DISTINCT 
        TeamNum,
        LastName,
        FirstName,
        City,
        ReimbursorName = CASE
            WHEN max(ReimbursorName) IN ('R1', 'E1')
                THEN '1' 
            WHEN max(ReimbursorName) IN ('R2', 'E2')
                THEN '2'
            ELSE '3'
            END,
        PatientID 
    FROM
        (
        SELECT
            TeamNum = CASE 
                    WHEN T.TeamName = 'Alpha Team'
                        THEN '1'
                    WHEN T.TeamName IN ('Bravo Team', 'Charlie Team')
                        THEN '2'
                    WHEN T.TeamName = 'Delta Team'
                        THEN '3'
                    ELSE '<Undefined>'
                    END,
            P.PatientLastName AS LastName,
            P.PatientFirstName AS FirstName,
            R.PrimaryCity AS City,
            ReimbursorName = CASE
                    WHEN RE.ReimbursorDescription = 'Medicare'
                        Then 'R1'
                    WHEN RE.ReimbursorDescription = 'Medicaid'
                        Then 'R2'
                    ELSE 'R3'
                    END,
            P.PatientID AS PatientID
        FROM 
            PatReferrals PR LEFT JOIN Patient P ON PR.PatientID = P.PatientID,
            Patient P LEFT OUTER JOIN Rolodex R ON P.RolodexID = R.RolodexID,
            PatReferrals PR LEFT OUTER JOIN PatReimbursors PRE ON PR.PatientID = PRE.PatientID,
            PatReimbursors PRE LEFT OUTER JOIN Reimbursors RE ON PRE.ReimbursorID = RE.ReimbursorID,
            PatReferrals PR FULL OUTER JOIN Teams T ON PR.TeamID = T.TeamID
        WHERE 
            PR.ReferralDate BETWEEN GETDATE()-4 AND GETDATE()-1
            AND PR.Status <> 'R' 
            AND PRE.CoveragePriority = '1'
            AND PRE.ExpirationDate IS NULL 
    
        UNION ALL
    
        SELECT
            TeamNum = CASE 
                    WHEN T.TeamName = 'Alpha Team'
                        THEN '1'
                    WHEN T.TeamName IN ('Bravo Team', 'Charlie Team')
                        THEN '2'
                    WHEN T.TeamName = 'Delta Team'
                        THEN '3'
                    ELSE '<Undefined>'
                    END,
            P.PatientLastName AS LastName,
            P.PatientFirstName AS FirstName,
            R.PrimaryCity AS City,
            ReimbursorName = CASE
                    WHEN RE.ReimbursorDescription = 'Medicare'
                        Then 'E1'
                    WHEN RE.ReimbursorDescription = 'Medicaid'
                        Then 'E2'
                    ELSE 'E3'
                    END,
            P.PatientID AS PatientID
        FROM 
            PatReferrals PR LEFT JOIN Patient P ON PR.PatientID = P.PatientID,
            Patient P LEFT OUTER JOIN Rolodex R ON P.RolodexID = R.RolodexID,
            PatReferrals PR LEFT OUTER JOIN PatEligibilities PE ON PR.PatientID = PE.PatientID,
            PatEligibilities PE LEFT OUTER JOIN Reimbursors RE ON PE.ReimbursorID = RE.ReimbursorID,
            PatReferrals PR FULL OUTER JOIN Teams T ON PR.TeamID = T.TeamID
        WHERE 
            PR.ReferralDate BETWEEN GETDATE()-4 AND GETDATE()-1
            AND PR.Status <> 'R' 
            AND PE.Status <> 'V'
            AND PE.ApplicationDate BETWEEN DATE(PR.ReferralDate)-5 AND DATE('2100/01/01')
        ) 
    
    AS DUMMYTBL
    GROUP BY
        TeamNum,
        LastName,
        FirstName,
        City,
        PatientID
    ORDER BY 
        DUMMYTBL.LastName ASC,
        DUMMYTBL.FirstName ASC
    

    感谢您提供的所有回复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 1970-01-01
      • 2018-12-08
      • 2021-04-01
      相关资源
      最近更新 更多