2012-10-19 40 views
6

truy vấn trục của tôi tạo ra:tham gia một trục với một bảng phức tạp

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

đây là truy vấn:

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 

tôi cần phải mang theo số ngày tối đa/phút cho mỗi lần thử nghiệm, (ví [1], [2], [3], v.v.) từ bảng này:

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

bảng trên được tạo bởi:

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 

bảng kết quả mà tôi cần để có được:

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

làm thế nào để tham gia hai bảng? tốc độ không quan trọng! cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn.

+0

nên trông giống như nó phải tham gia cả trên client_id VÀ 1, 2, 3, 4 .. (đó là TimesTested) –

+0

vâng thats đúng – user1760020

+0

đâu @JNK khi bạn cần anh ta? –

Trả lời

1

Không phải là đẹp nhất, nhưng tôi lại truy vấn ban đầu của bạn còn nguyên vẹn và đặt nó tất cả trong một [lớn] tuyên bố:

;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! điều này có vẻ tuyệt vời !! bạn không muốn ném trong một số điều kiện mà maxdate1 không phải là null và mindate1 không phải là null và tối đa date2 không phải là null vv ... và làm LEFT tham gia thay vì tham gia bên trong? –

+0

có thể sai, tôi không biết :) –

+0

Vâng, một bên trái tham gia nên bao gồm những người được null, tôi sẽ thêm đó. – d89761

1

Không cần phải tham gia hai truy vấn. Hơn nữa, không cần phải sử dụng tự tham gia. Đây là cách bạn có thể đi về việc chọn lựa tất cả các dữ liệu cần thiết trong một truy vấn:

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 
; 

Dưới đây là cách hoạt động:

  1. Các CTE đầu tiên (counted) nhóm dữ liệu bằng cách client_idpatient_id và tính toán hàng đếm, ngày tối đa và ngày tối thiểu cho mỗi nhóm.

  2. CTE thứ hai (counted2) nhóm kết quả trước được đặt bởi client_id và cột chứa số hàng (được gọi là TimesTested) và một lần nữa đếm các hàng và tìm ngày tối đa và tối thiểu cho mỗi nhóm. Các rowset sản xuất tương tự như bảng thứ hai trong câu hỏi của bạn, ngoại trừ count chỉ là COUNT(*) (vì đó là những gì truy vấn đầu tiên của bạn tính toán). Ngoài ra, tất cả các kết quả tổng hợp được chuyển đổi thành chuỗi, để chuẩn bị cho chúng để bỏ cấm.

  3. Các CTE sau, unpivoted, hiện unpivoting nêu trên, tạo ra một rowset như thế này:

    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. Các CTE thức, pivoted, thực hiện bước cuối cùng, xoay vòng về kết quả trước đó CTE, cuối cùng tạo ra sản lượng bạn muốn.

+0

hoàn toàn không thể tin được. bạn là một thiên tài. –

+0

@ АртёмЦарионов: Cảm ơn bạn, bạn rất tử tế. –

+0

bạn có chắc chắn bằng cách đếm (*) trong count2 không? bạn không nên tổng hợp và nhận được trung bình của các testfrequencies? –

Các vấn đề liên quan