有没有比做UNION ALL更简单的方法?

时间:2012-11-21 22:06:18

标签: sql sql-server sql-server-2008 tsql

我有一个相当大的查询,它选择某个日期范围内的数据。

我想根据年份对数据进行分组。

现在我有:

;with mappingTable as
(
select b.CLIENT_ID,f.patient_id,f.received_date,f.SPECIMEN_ID
from F_ACCESSION_DAILY f
join
(
select f.client_id,a.patient_id
from
(
SELECT
       max(received_date) AS received_date
     , patient_id         AS Patient_ID
FROM F_ACCESSION_DAILY
group by PATIENT_ID
) a
join F_ACCESSION_DAILY f
on f.PATIENT_ID=a.Patient_ID
and f.RECEIVED_DATE=a.received_date
) b
on b.Patient_ID=f.PATIENT_ID
where f.RECEIVED_DATE between '20100101' and '20110101' - as you can see this data is only for 2010
) ---there's much more to this query

正如您所看到的,此数据仅适用于2010年

但我希望所有年份都union all:2008年,2009年,2010年,2011年,2012年......

如何在不重写查询5次并在所有查询之间执行union all的情况下执行此操作?

这是整个怪物查询:

;with mappingTable as
(
select b.CLIENT_ID,f.patient_id,f.received_date,f.SPECIMEN_ID
from F_ACCESSION_DAILY f
join
(
select f.client_id,a.patient_id
from
(
SELECT
       max(received_date) AS received_date
     , patient_id         AS Patient_ID
FROM F_ACCESSION_DAILY
group by PATIENT_ID
) a
join F_ACCESSION_DAILY f
on f.PATIENT_ID=a.Patient_ID
and f.RECEIVED_DATE=a.received_date
) b
on b.Patient_ID=f.PATIENT_ID
where f.RECEIVED_DATE between '20100101' and '20110101'
)
,
  counted as(
SELECT
PATIENT_ID,
    client_id,
    --case when COUNT(*)>=12 then 12 else COUNT(*) end  TimesTested, 
    COUNT(*) as timestested,
    case when count(*)>1 then
    (datediff(day,MIN(received_date),max(received_date)))
  /(COUNT(*)-1) 
 else
0
end as testfreq
  FROM mappingTable
  GROUP BY
    client_id,
    patient_id    

),counted2 as (
  SELECT
    client_id,
   TimesTested,
    CAST(COUNT(*) AS varchar(30)) AS count,
    CAST(AVG(testfreq) as varchar(30)) as TestFreq,
    CAST(STDEV(TestFreq) as varchar(30)) Stdv
  FROM counted
  GROUP BY
    client_id,
    TimesTested
    ),







    counted3 as 
     (
  SELECT
  patient_id,
    client_id,
   TimesTested,
    CAST(COUNT(*) AS varchar(30)) AS count,
    AVG(testfreq) as TestFreq
  FROM counted
  GROUP BY
    client_id,
    TimesTested,
    PATIENT_ID
    )
    ,
    CountOver12 as
    (    select client_id,count(*) count
    from counted
    where timestested>12
    group by CLIENT_ID)
    ,
    TotalAvgTestFreq as (

    select client_id, SUM(testfreq) / count(testfreq) TotalAvgTestFreq
    from counted3
    group by client_id
    )



    ,
unpivoted AS (
  SELECT
    client_id,
    ColumnName + CAST(TimesTested AS varchar(10)) AS ColumnName,
    ColumnValue
  FROM counted2
  UNPIVOT (
    ColumnValue FOR ColumnName IN (count, TestFreq,stdv)
  ) u
),
pivoted AS (
  SELECT
    client_id clientid,
    count1, TestFreq1,stdv1,
    count2, TestFreq2,stdv2,
    count3, TestFreq3,stdv3,
    count4, TestFreq4,stdv4,
    count5, TestFreq5,stdv5,
    count6, TestFreq6,stdv6,
    count7, TestFreq7,stdv7,
    count8, TestFreq8,stdv8,
    count9, TestFreq9,stdv9,
    count10, TestFreq10,stdv10,
    count11, TestFreq11,stdv11,
    count12, TestFreq12,stdv12
  FROM unpivoted
  PIVOT (
    MAX(ColumnValue) FOR ColumnName IN (
      count1,TestFreq1,stdv1,
      count2,TestFreq2,stdv2,
      count3,TestFreq3,stdv3,
      count4,TestFreq4,stdv4,
      count5,TestFreq5,stdv5,
      count6,TestFreq6,stdv6,
      count7,TestFreq7,stdv7,
    count8, TestFreq8,   stdv8,
    count9, TestFreq9,   stdv9,
    count10, TestFreq10,stdv10,
    count11, TestFreq11,stdv11,
    count12, TestFreq12,stdv12
    )
  ) p
)
,
PatientStats as
(
select 
 distinct
f.client_id
,datediff(MM,c.mlis_date_established,GETDATE()) MonthsCustomer
,count(distinct patient_id) TotalPatients
,count(distinct specimen_id) TotalSpecimens
from mappingTable f
left join D_CLIENT c
on f.CLIENT_ID=c.CLIENT_ID
group by f.client_id,c.mlis_date_established
)
,
Over12
as
(
select client_id,SUM(c) sumcount from
(
select CLIENT_ID,COUNT(*) c
from mappingTable
group by CLIENT_ID,PATIENT_ID
having count(*)>12
) a
group by client_id
),
GetMedian as(

    select client_id, avg(timestested) median_testfreq
from
(
    select client_id,
           timestested,
           rn=row_number() over (partition by CLIENT_ID
                                 order by timestested),
           c=count(timestested) over (partition by CLIENT_ID)
    from counted3
    where timestested>1
) g
where rn in (round(c/2,0),c/2+1)
group by client_id
   )
, final as (
SELECT p.*,pivoted.*,c12.count [Count13+],Over12.sumcount SumofGreaterThan12,t.TotalAvgTestFreq,median.median_testfreq
FROM pivoted
left join PatientStats p
on p.CLIENT_ID=pivoted.CLIENTID
left join Over12
on over12.CLIENT_ID=p.CLIENT_ID
left join TotalAvgTestFreq t
on t.CLIENT_ID=p.CLIENT_ID
left join CountOver12 C12
on c12.CLIENT_ID=p.CLIENT_ID
left join GetMedian median
on median.CLIENT_ID=p.CLIENT_ID
where p.CLIENT_ID not in (select CLIENTid from SalesDWH..TestPractices)
)
/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM final
/* Drop the cloumns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN clientid
/* Get results and drop temp table */
SELECT * FROM #TempTable
DROP TABLE #TempTable

1 个答案:

答案 0 :(得分:1)

创建表函数:

CREATE FUNCTION fn_get_data_by_date_range
(
   @start AS VARCHAR(8),
   @end AS VARCHAR(8)
)
RETURNS TABLE
AS 
RETURN 
(
   ...your query...
   WHERE f.RECEIVED_DATE BETWEEN @start AND @end
)

然后你可以UNION对该函数的不同调用:

SELECT * FROM fn_get_data_by_date_range('20100101','20110101')
UNION ALL
SELECT * FROM fn_get_data_by_date_range('20090101','20100101')
UNION ALL
....
UNION ALL
SELECT * FROM fn_get_data_by_date_range('20070101','20080101')