多个行用于相同的标识符

时间:2016-04-29 21:41:18

标签: sql sql-server tsql

我正在尝试创建一个查询,我不必使用GROUP BY来获取我的项目,否则他们会将数据拆分成行。以下是我所拥有的内容,但是我为相同的patient_id获取了多行,而last_servicelast_payment从未出现在同一行中。我得到3行,它们似乎被last_servicelast_payment拆分,并且两行都是NULL。这是我的疑问:

WITH adj_rep_les AS(
SELECT DISTINCT t.clinic, t.patient_id, a.adj_desc
FROM transactions t
LEFT JOIN adjustments a
    ON(t.clinic=a.clinic AND a.adjustment_id=t.adjustment_id)
WHERE a.adj_desc LIKE '%TAB%'
AND time_ran > '2016-03-27')

SELECT DISTINCT
        c.clinic_id,
        w.patient_id,
        p.city,
        p.state,
        p.zipcode,
        SUM(t.amount) OVER (PARTITION BY w.clinic, w.patient_id) AS balance,
        CASE WHEN t.impacts='P' THEN FIRST_VALUE(t.date_entered) OVER (PARTITION BY w.clinic, w.patient_id ORDER BY t.date_entered DESC) END AS last_service,
        CASE WHEN t.impacts='C' THEN FIRST_VALUE(t.date_entered) OVER (PARTITION BY w.clinic, w.patient_id ORDER BY t.date_entered DESC) END AS last_payment,
        FIRST_VALUE(s.description) OVER (PARTITION BY w.clinic, w.patient_id ORDER BY t.date_entered DESC) AS service_done

FROM adj_rep_les w
LEFT JOIN clinic_master c
    ON (w.clinic=c.clinic)
LEFT JOIN patient p
    ON (w.clinic=p.clinic AND w.patient_id=p.patient_id)
LEFT JOIN transactions t
    ON (w.clinic=t.clinic AND w.patient_id=t.patient_id)
LEFT JOIN services s
    ON (t.clinic=s.clinic AND t.service_code=s.service_code)

有什么想法?我还要提到FIRST_VALUE中的CASE似乎无法正常工作并给出相同的结果,而不管忽略t.impacts的过滤器。或者尝试在案例中使用MAX(t.date_entered)但由于GROUP BY是一个聚合函数而需要MAX

示例数据结果: Sample Data

提前致谢。

1 个答案:

答案 0 :(得分:3)

有些问题是:

  • transactions的联接会产生每笔交易的记录,而每位患者只需要一条记录。要解决此问题,您可以在子查询中执行事务选择,并从中筛选每个患者的一条记录;
  • CASE构造打败了每个患者想要一条记录的逻辑,因为你可能永远不会同时拥有这两个条件。相反,这些CASE构造应出现在某些聚合中。

少了一个问题:

  • 您可以在显然LEFT JOIN具有相同结果的地方使用INNER JOIN。后者通常具有更好的性能,因此我建议尽可能使用它。
  • 您不在CTE之外使用adj_desc,因此无需SELECT它;
  • 您不会将master_clinic表用于除已有的主键值以外的任何其他值,因此我认为您可以将该表格保留下来;
  • 您使用列clinic来表示参照完整性,但请选择clinic_id。我认为这是一个错字。

以下是我建议的查询:

WITH adj_rep_les AS (
    SELECT DISTINCT t.clinic, t.patient_id
    FROM       transactions t
    INNER JOIN adjustments a
           ON  t.clinic=a.clinic 
           AND a.adjustment_id=t.adjustment_id
    WHERE      a.adj_desc LIKE '%TAB%'
    AND        time_ran > '2016-03-27')
SELECT DISTINCT
            w.clinic,
            w.patient_id,
            p.city,
            p.state,
            p.zipcode,
            x.balance,
            x.last_service,
            x.last_payment,
            x.service_done
FROM        adj_rep_les w
INNER JOIN  patient p
        ON  w.clinic=p.clinic
        AND w.patient_id=p.patient_id
INNER JOIN  (
            SELECT     t.clinic,
                       t.patient_id,
                       SUM(t.amount)
                           OVER (PARTITION BY t.clinic, t.patient_id) AS balance,
                       MAX(CASE WHEN t.impacts='P' THEN t.date_entered END) 
                           OVER (PARTITION BY t.clinic, t.patient_id) AS last_service,
                       MAX(CASE WHEN t.impacts='C' THEN t.date_entered END) 
                           OVER (PARTITION BY t.clinic, t.patient_id) AS last_payment,
                       ROW_NUMBER() 
                           OVER (PARTITION BY t.clinic, t.patient_id 
                               ORDER BY t.date_entered DESC) AS rn,
                       s.description AS service_done
            FROM       transactions t
            LEFT JOIN  services s
                   ON  t.clinic=s.clinic
                   AND t.service_code=s.service_code) as x
        ON  w.clinic=x.clinic
        AND w.patient_id=x.patient_id
        AND rn = 1

rn = 1条件可确保您从transaction表格中获得一条记录,该表格是针对特定患者和诊所的最新date_entered表。