2012-10-19 9 views
6

moje zapytanie obrotu generuje:łączący sworzeń z innego złożonego stołu

+-----------+----+----+---+---+---+---+---+ 
| 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 | 
+-----------+----+----+---+---+---+---+---+ 

oto zapytanie:

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 

muszę przynieść daty max/min dla każdego badanego czasu (na [1], [2], [3], etc.) z tej tabeli:

+-----------+-------------+-------+------------+------------+ 
| 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 | 
+-----------+-------------+-------+------------+------------+ 

powyższa tabela jest generowany przez:

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 

powstałej tabeli, że muszę dostać:

+-----------+----+----------+-----------+----+----------+-----------+---+----------+-----------+---+----------+-----------+-----+ 
| 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 |  | 
+-----------+----+----------+-----------+----+----------+-----------+---+----------+-----------+---+----------+-----------+-----+ 

Jak mogę dołączyć dwie tablice? prędkość nie ma znaczenia! dziękuję bardzo za życzliwą pomoc.

+0

więc wygląda na to, że ma się przyłączyć zarówno na client_id ORAZ 1, 2, 3, 4 .. (co jest TimesTested) –

+0

tak to jest to poprawne – user1760020

+0

gdzie jest @JNK kiedy go potrzebujemy? –

Odpowiedz

1

nie najładniejsza, ale zostawiłem oryginalne zapytań nienaruszone i umieścić to wszystko w jednym [big] Oświadczenie:

;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! to wygląda prety niesamowite! nie chcesz rzucić w niektórych warunkach, gdzie maxdate1 nie jest null i mindate1 nie jest null i max date2 nie jest null itp ... ... i czy LEFT dołączyć zamiast wewnętrznego join? –

+0

może im źle, nie wiem :) –

+0

Tak, lewy dołączyć powinien pokryć te są puste, dodam, że. – d89761

1

Nie ma potrzeby, aby złączyć dwa pytania. Co więcej, nie ma potrzeby używania samołączenia. Oto w jaki sposób można przejść o wybraniu wszystkich niezbędnych danych w jednym zapytaniu:

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 
; 

Oto jak to działa:

  1. Pierwszy CTE (counted) grupuje dane według client_id i patient_id i oblicza wiersz liczyć, maksymalną datę i minimalną datę dla każdej grupy.

  2. Drugi CTE (counted2) grupy poprzedni zestaw wyników przez client_id i kolumny zawierającej liczby rzędów (zwany TimesTested) i ponownie liczy wierszy i znajduje maksymalna i minimalna termin grupie. Utworzony zestaw wierszy jest podobny do drugiej tabeli w pytaniu, z tym że count to tylko COUNT(*) (ponieważ to właśnie oblicza pierwsze zapytanie). Dodatkowo wszystkie zagregowane wyniki są konwertowane na łańcuchy, aby przygotować je do rozpinania.

  3. Poniżej CTE, unpivoted, czy wyżej wymienione unpivoting, tworząc zestaw wierszy tak:

    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. Końcowy CTE, pivoted wykonuje ostatni etap, wychylnego w wyniku poprzedniego CTE, ostatecznie wytwarzając żądany wynik.

+0

absolutnie niewiarygodne działanie. jesteś geniuszem. –

+0

@ АртёмЦарионов: Dziękuję, jesteś bardzo miły. –

+0

czy jesteś pewny, że powinien się on liczyć (*) w count2? nie powinieneś podsumowywać i uzyskiwać średnie z testowych częstotliwości? –

Powiązane problemy