2012-10-19 6 views
6

私のピボットクエリが生成します。別の複雑なテーブルとピボットに参加

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

ここにクエリです:

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 

私は(のために、テストしたすべての時間のための最大/最小の日付を持参する必要がありますが、 [1]、[2]、[3]、など)この表から

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

上記テーブルが生成されます:私は取得する必要があり

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 

結果のテーブル:

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

は、どのように私は2つのテーブルを結合しますか?速度は重要ではありません!あなたの親切な助けをありがとう。

+0

ので、それはclient_idの上の両方に参加しているように見える1、2、3、4 ... –

+0

はい正しいのthats(TimesTestedがある) – user1760020

+0

あなたが彼を必要とするときどこ@JNKがありますか? –

答えて

1

ないきれいな、私はそのまま元のクエリを離れ、1 [大]文でそれをすべて置く:

;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!これは素晴らしいプレティに見える!! maxdate1がnullでなく、mindate1がnullでなく、max2がnullなどでない条件をスローしたくないのですか?内部結合の代わりにLEFT結合を実行しますか? –

+0

多分私は間違っている、私は知らない:) –

+0

ええ、左の結合はそれらがnullであることをカバーする必要があります、私はそれを追加します。 – d89761

1

2つのクエリを結合する必要はありません。さらに、自己結合を使う必要もありません。ここでは、1つのクエリ内のすべての必要なデータを選択するに取り掛かることができる方法だ:client_idpatient_idによる最初のCTE(counted)グループデータ

  1. と行を計算します。

    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 
    ; 
    

    ここでは、これがどのように動作するかですカウント、各グループの最大日付と最小日付。

  2. 第二CTE(counted2)グループ前の結果がclient_id及び(TimesTested呼ばれる)行数を含む列によって設定され、再度行をカウントし、max及び群当たり最小の日付を見つけます。生成された行セットは、countがちょうどCOUNT(*)であることを除いて、質問の2番目のテーブルと似ています(これは最初のクエリで計算されるためです)。さらに、集計されたすべての結果は、ピリオドに変換されてピリオドに変換されます。

  3. 以下のCTE、unpivoted、このような行セットを生成する、上記アンピボットを行います

    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. 最終CTE、pivoted、最後のステップは、前の結果の旋回を行いますCTE、最終的にあなたが望む出力を生み出します。

+0

絶対に信じられないほどのパフォーマンス。あなたは天才です。 –

+0

@АртёмЦарионов:ありがとう、あなたはとても親切です。 –

+0

count2でcount(*)するべきではないでしょうか? testfrequenciesの合計を集計し平均してはいけませんか? –