2016-04-29 19 views
0

Ich versuche, eine Abfrage zu erstellen, die ich nicht verwenden muss GROUP BY, um meine Elemente in anderen Daten in Zeilen aufgeteilt werden. Hier ist was ich habe, was läuft, aber ich bekomme mehrere Zeilen für die gleichen patient_id und die last_service und last_payment nie in der gleichen Zeile erscheinen. Ich bekomme 3 Zeilen, wo sie sich zu teilen scheinen, durch last_service, last_payment, und eine Zeile, wo beide NULL sind. Hier ist meine Frage:Mehrere Zeilen für denselben Bezeichner

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) 

Irgendwelche Gedanken? Ich würde auch erwähnen, dass die FIRST_VALUE innerhalb der CASE scheinen nicht zu arbeiten und geben das gleiche Ergebnis, unabhängig davon, ob Sie den Filter für t.impacts ignorieren. mit MAX (t.date_entered) im Fall Alternativ versucht, aber das erfordert eine GROUP BY aufgrund MAX aggregierter Funktion

Beispieldaten Ergebnisse sind: Sample Data

Vielen Dank im Voraus.

+0

Nur eine Vermutung, wie keine Beispieldaten und ddl zur Verfügung gestellt. Versuchen Sie 'CASE WHEN t.impacts =' P 'zu verschieben THEN FIRST_VALUE (t.date_entered) OVER (PARTITION VON w.clinic, w.patient_id ORDER BY t.date_entered DESC) END AS last_service, FALL WENN t.impacts =' C 'THEN FIRST_VALUE (t.date_entered) OVER (PARTITION BY w.clinic, w.patient_id ORDER BY t.date_entered DESC) END ALS last_payment, 'to CTE und pivotieren sie in CTE und löscht den Join mit der Transaktion in main SELECT. – Serg

Antwort

3

Einige der Themen sind:

  • Die in einem Datensatz pro Transaktion mit transactions Ergebnissen kommen, während Sie nur einen Datensatz wollen pro Patient würde. Um dies zu lösen, könnten Sie die Transaktionen in einer Unterabfrage auswählen und einen Datensatz pro Patient daraus filtern;
  • Die CASE Konstrukte besiegen die Logik, in der Sie einen Datensatz pro Patient haben möchten, da Sie nie beide Bedingungen gleichzeitig wahr haben können. Stattdessen sollten diese CASE Konstrukte innerhalb einer Aggregation erscheinen.

Weniger ein Problem:

  • Sie LEFT JOIN an Orten, wo es klar ist, dass ein INNER JOIN die gleichen Ergebnisse haben würde. Letzteres hat im Allgemeinen eine bessere Leistung, also würde ich vorschlagen, es wo möglich zu verwenden.
  • Sie verwenden adj_desc nicht außerhalb des CTE, so dass es keine Notwendigkeit gibt, SELECT es;
  • Sie verwenden die master_clinic Tabelle für alles andere als den Primärschlüsselwert, den Sie bereits haben, so dass ich denke, dass Sie diese Tabelle verlassen können;
  • Sie verwenden die Spalte für die referenzielle Integrität, aber wählen Sie clinic_id. Ich nehme an, das ist ein Tippfehler. Hier

ist die Abfrage würde ich vorschlagen:

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 

Die rn = 1 Bedingung stellt sicher, Sie erhalten genau einen Datensatz aus der transaction Tabelle, die man mit den jüngsten date_entered für einen bestimmten Patienten und Klinik.

+0

@OM Asphyxiate, hat dies Ihr Problem gelöst? Könnten Sie etwas Feedback geben? – trincot

+0

Das schien tatsächlich zu funktionieren, wie ich es mir erhofft hatte. Ich bin immer noch ziemlich neu in SQL und habe mich mit dem, was ich bisher gelernt habe, zufrieden gegeben. Ich schätze all die Hilfe und Einsicht in die Sache. –

+0

Gern geschehen. Zögere nicht, neue Fragen zu stellen! – trincot

Verwandte Themen