2012-10-19 9 views
6

meine Pivot-Abfrage generiert:einen Schwenk mit einer anderen komplexen Tabelle Verbindungs ​​

+-----------+----+----+---+---+---+---+---+ 
| client_id | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
+-----------+----+----+---+---+---+---+---+ 
| 216436 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 110522 | 76 | 3 | 0 | 0 | 0 | 0 | 0 | 
| 214981 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 
| 216360 | 52 | 1 | 0 | 0 | 0 | 0 | 0 | 
| 102574 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 211754 | 97 | 14 | 2 | 0 | 0 | 0 | 0 | 
| 210734 | 8 | 4 | 0 | 0 | 0 | 0 | 0 | 
| 10| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 101840 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 
+-----------+----+----+---+---+---+---+---+ 

hier ist die Abfrage:

select client_id, 
    [1],[2],[3],[4],[5],[6],[7] -- these are timestested (the amount of times tested) 
    from 
    ( SELECT DISTINCT CLIENT_ID 
    , PATIENT_ID 
    , count(*) over (partition by client_id, patient_id) AS patientcount 

    from f_accession_daily) as SourceTable 
    PIVOT 
    (
    count(patient_id) 
    for patientcount in ([1],[2],[3],[4],[5],[6],[7]) 
    ) as pivottable 

Ich brauche die max/min Daten für jedes Mal getestet zu bringen, (für [1], [2], [3], usw.) aus dieser Tabelle:

+-----------+-------------+-------+------------+------------+ 
| client_id | TimesTested | count | maxRecDate | minRecDate | 
+-----------+-------------+-------+------------+------------+ 
| 100034 |   2 |  1 | 6/25/2008 | 6/23/2008 | 
| 100034 |   1 | 20 | 6/30/2008 | 6/19/2008 | 
| 100038 |   3 |  1 | 7/25/2008 | 7/23/2008 | 
| 100038 |   1 |  4 | 7/25/2008 | 7/1/2008 | 
| 100050 |   1 | 15 | 8/11/2008 | 7/14/2008 | 
| 100060 |   1 |  2 | 8/12/2008 | 7/29/2008 | 
| 100070 |   1 |  3 | 8/15/2008 | 8/15/2008 | 
| 100049 |   1 |  3 | 8/22/2008 | 7/11/2008 | 
| 100029 |   3 |  2 | 8/25/2008 | 6/18/2008 | 
+-----------+-------------+-------+------------+------------+ 

die obige Tabelle erzeugt von:

SELECT a.client_id AS client_id 
,a.patientcount TimesTested 
    , count(a.patientcount)/a.patientcount AS count 
    , max(f.received_date) AS maxRecDate 
    , min(f.received_date) AS minRecDate 
FROM 
(
    SELECT DISTINCT CLIENT_ID 
    , PATIENT_ID 
    , count(*) over (partition by client_id, patient_id) AS patientcount 

    from f_accession_daily 

) AS a 
JOIN F_ACCESSION_DAILY AS f ON a.CLIENT_ID = f.CLIENT_ID 
    AND a.PATIENT_ID = f.PATIENT_ID 

GROUP BY a.CLIENT_ID, a.patientcount 

die resultierende Tabelle, die ich bekommen müssen:

+-----------+----+----------+-----------+----+----------+-----------+---+----------+-----------+---+----------+-----------+-----+ 
| client_id | 1 | maxdate1 | mindate1 | 2 | maxdate2 | mindate2 | 3 | maxdate3 | mindate3 | 4 | maxdate4 | mindate4 | 5 | 
+-----------+----+----------+-----------+----+----------+-----------+---+----------+-----------+---+----------+-----------+-----+ 
| 216436 | 9 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | etc | 
| 110522 | 76 | 1/1/2011 | 1/23/1984 | 3 | 1/1/2011 | 1/23/1984 | 0 | 1/1/2011 | 1/23/1984 | 0 | 2/1/2011 | 1/23/1984 |  | 
| 214981 | 0 | 1/1/2013 | 1/23/1985 | 1 | 1/1/2013 | 1/23/1985 | 0 | 1/1/2013 | 1/23/1985 | 0 | 1/1/2013 | 1/23/1985 |  | 
| 216360 | 52 | 1/1/2011 | 1/23/1985 | 1 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 |  | 
| 102574 | 1 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2014 | 1/23/1980 | 0 | 2/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 |  | 
| 211754 | 97 | 1/1/2012 | 1/23/1985 | 14 | 1/1/2012 | 1/23/1985 | 2 | 1/1/2012 | 1/23/1985 | 0 | 1/1/2012 | 1/23/1985 |  | 
| 210734 | 8 | 1/1/2011 | 1/23/1984 | 4 | 1/1/2011 | 1/23/1984 | 0 | 1/1/2011 | 1/23/1984 | 0 | 1/1/2011 | 1/23/1984 |  | 
| 10| 1 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1987 |  | 
| 101840 | 2 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1980 | 0 | 1/1/2011 | 1/23/1985 | 0 | 1/1/2011 | 1/23/1985 |  | 
+-----------+----+----------+-----------+----+----------+-----------+---+----------+-----------+---+----------+-----------+-----+ 

wie trete ich die beiden Tabellen? die Geschwindigkeit spielt keine Rolle! Vielen Dank für Ihre freundliche Hilfe.

+0

so aussieht wie es sowohl auf client_id und die 1, 2, 3, 4 .. beitreten hat (das ist TimesTested) –

+0

ja richtig das ist – user1760020

+0

wo ist @JNK wenn man ihn braucht? –

Antwort

1

nicht die schönste, aber ich Ihre Original-Anfragen erhalten und sie alle in einer [großen] Anweisung setzen:

;WITH 
PivotQuery as (
    select client_id, 
     [1],[2],[3],[4],[5],[6],[7] 
     from 
     ( SELECT DISTINCT CLIENT_ID 
     , PATIENT_ID 
     , count(*) over (partition by client_id, patient_id) AS patientcount 

     from f_accession_daily) as SourceTable 
     PIVOT 
     (
     count(patient_id) 
     for patientcount in ([1],[2],[3],[4],[5],[6],[7]) 
     ) as pivottable), 

MinMaxTimes as (
    SELECT a.client_id AS client_id 
    ,a.patientcount TimesTested 
     , count(a.patientcount)/a.patientcount AS count 
     , max(f.received_date) AS maxRecDate 
     , min(f.received_date) AS minRecDate 
    FROM 
    (
     SELECT DISTINCT CLIENT_ID 
     , PATIENT_ID 
     , count(*) over (partition by client_id, patient_id) AS patientcount 

     from f_accession_daily 

    ) AS a 
    JOIN F_ACCESSION_DAILY AS f ON a.CLIENT_ID = f.CLIENT_ID 
     AND a.PATIENT_ID = f.PATIENT_ID 

    GROUP BY a.CLIENT_ID, a.patientcount), 

maxDates as (
SELECT client_id, [1] maxdate1, [2] maxdate2, [3] maxdate3, [4] maxdate4, [5] maxdate5, [6] maxdate6, [7] maxdate7 
FROM MinMaxTimes t 
PIVOT (max(maxRecDate) 
for TimesTested IN ([1], [2], [3], [4], [5], [6], [7]) 
) as p), 

minDates as (
SELECT client_id, [1] mindate1, [2] mindate2, [3] mindate3, [4] mindate4, [5] mindate5, [6] mindate6, [7] mindate7 
FROM MinMaxTimes t 
PIVOT (max(minRecDate) 
for TimesTested IN ([1], [2], [3], [4], [5], [6], [7]) 
) as p) 

SELECT p.client_id, 
    p.[1], max(maxdate1) maxdate1, max(mindate1) mindate1, 
    p.[2], max(maxdate2) maxdate2, max(mindate2) mindate2, 
    p.[3], max(maxdate3) maxdate3, max(mindate3) mindate3, 
    p.[4], max(maxdate4) maxdate4, max(mindate4) mindate4, 
    p.[5], max(maxdate5) maxdate5, max(mindate5) mindate5, 
    p.[6], max(maxdate6) maxdate6, max(mindate6) mindate6, 
    p.[7], max(maxdate7) maxdate7, max(mindate7) mindate7 
FROM PivotQuery p 
LEFT OUTER JOIN maxDates a ON p.client_id = a.client_id 
LEFT OUTER JOIN mindates i ON a.client_id = i.client_id 
GROUP BY p.client_id, p.[1], p.[2], p.[3], p.[4], p.[5], p.[6], p.[7] 
+0

WOW! das sieht schon super aus !! Willst du nicht in einige Bedingungen, wo maxdate1 ist nicht null und mindate1 ist nicht null und max date2 ist nicht null usw. ... und wollen LEFT Join statt innere Join werfen? –

+0

vielleicht bin ich falsch, ich weiß nicht :) –

+0

Yeah, eine linke Join sollte diejenigen, die Null sein, ich werde das hinzufügen. – d89761

1

Es gibt keine Notwendigkeit, die zwei Abfragen zu verbinden. Darüber hinaus ist es nicht notwendig, einen Self-Join zu verwenden. Hier ist, wie Sie über die Auswahl alle notwendigen Daten in einer Abfrage gehen könnte:

WITH counted AS (
    SELECT 
    client_id, 
    COUNT(*) AS TimesTested, 
    MAX(received_date) AS maxdate, 
    MIN(received_date) AS mindate 
    FROM f_accession_daily 
    GROUP BY 
    client_id, 
    patient_id 
), 
counted2 AS (
    SELECT 
    client_id, 
    TimesTested, 
    CAST(COUNT(*) AS varchar(30)) AS count, 
    CAST(MAX(maxdate) AS varchar(30)) AS maxdate, 
    CAST(MIN(mindate) AS varchar(30)) AS mindate 
    FROM counted 
    GROUP BY 
    client_id, 
    TimesTested 
), 
unpivoted AS (
    SELECT 
    client_id, 
    ColumnName + CAST(TimesTested AS varchar(10)) AS ColumnName, 
    ColumnValue 
    FROM counted2 
    UNPIVOT (
    ColumnValue FOR ColumnName IN (count, maxdate, mindate) 
) u 
), 
pivoted AS (
    SELECT 
    client_id, 
    count1, maxdate1, mindate1, 
    count2, maxdate2, mindate2, 
    count3, maxdate3, mindate3, 
    count4, maxdate4, mindate4, 
    count5, maxdate5, mindate5, 
    count6, maxdate6, mindate6, 
    count7, maxdate7, mindate7 
    FROM unpivoted 
    PIVOT (
    MAX(ColumnValue) FOR ColumnName IN (
     count1, maxdate1, mindate1, 
     count2, maxdate2, mindate2, 
     count3, maxdate3, mindate3, 
     count4, maxdate4, mindate4, 
     count5, maxdate5, mindate5, 
     count6, maxdate6, mindate6, 
     count7, maxdate7, mindate7 
    ) 
) p 
) 
SELECT * 
FROM pivoted 
; 

Hier ist, wie das funktioniert:

  1. Der erste CTE (counted) Gruppen Daten von client_id und patient_id und berechnet die Zeile zählen, das maximale Datum und das Mindestdatum für jede Gruppe.

  2. Der zweite CTE (counted2) Gruppen das vorherige Ergebnis eingestellt durch client_id und Spalte enthält, zählt die Zeilenzahl (genannt TimesTested) und wieder die Zeilen und findet die Maximal- und Minimaldaten pro Gruppe. Das erzeugte Rowset ähnelt der zweiten Tabelle in Ihrer Frage, außer count ist nur COUNT(*) (weil das Ihre erste Abfrage berechnet). Darüber hinaus werden alle aggregierten Ergebnisse in Zeichenfolgen konvertiert, um sie für die Aufhebung der Aufhebung vorzubereiten.

  3. Die folgenden CTE, unpivoted, wird die oben erwähnte unpivoting, eine rowset wie diese Herstellung:

    client_id ColumnName ColumnValue 
    --------- ---------- ----------- 
    211754  count1  97 
    211754  maxdate1 1/1/2012 
    211754  mindate1 1/23/1985 
    211754  count1  14 
    211754  maxdate1 1/1/2012 
    211754  mindate1 1/23/1985 
    ... 
    
  4. Die endgültige CTE, pivoted führt der letzte Schritt, der dem Ergebnis des vorherigen Schwenk CTE, die letztendlich die gewünschte Ausgabe liefert.

+0

absolut unglaubliche Leistung. du bist ein Genie. –

+0

@ АртёмЦарионов: Vielen Dank, Sie sind sehr freundlich. –

+0

bist du sicher, dass es count2 zählen soll (*)? sollten Sie nicht summieren und Durchschnittswerte der Testfrequenzen erhalten? –

Verwandte Themen