2010-06-26 46 views
1

已存在這樣的數據庫架構SQL問題: alt text http://img156.imageshack.us/img156/9017/2706.png有12子查詢

我需要編寫查詢。

對於每位醫生,我需要2009年平均月訪問費用。 結果是(name_of_doctor,january,febriary,...,12月)

我知道如何做到這一點與12子查詢。存在另一種更方便的方式?

+1

您使用的是rdbms(sql server,oracle,mysql)嗎? – RRUZ 2010-06-27 00:01:16

+0

我需要可以在大多數rdbms中工作的解決方案。但主要是我們公司使用oracle。 – 2010-06-27 08:40:34

回答

1

我只是做了正常使用GROUP BY選擇在本月,有你的UI手柄顯示它爲12列橫跨。如果你真的需要這樣做,那麼這應該工作:

SELECT 
    D.name, 
    AVG(CASE WHEN MONTH(V.visit_date) = 1 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 2 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 3 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 4 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 5 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 6 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 7 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 8 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 9 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 10 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 11 THEN V.cost ELSE NULL END), 
    AVG(CASE WHEN MONTH(V.visit_date) = 12 THEN V.cost ELSE NULL END) 
FROM 
    Doctors D 
INNER JOIN Visits V ON 
    V.id_doc = D.id AND 
    V.visit_date BETWEEN '2009-01-01' AND '2009-12-31' 
GROUP BY 
    D.name 
ORDER BY 
    D.name 

您可能需要根據您的RDBMS更改日期函數。此外,你可能需要擺弄邊緣情況 - 如果你的日期有一個時間組件,它不會在12/31捕捉到行。

最後,我不知道這個RDBMS之間是否有變化,我現在無法測試,但如果AVG​​以0代價計算NULL而不是對它們進行折扣,那麼您可能需要自己做averag - SUM( CASE ...成本... 0)/ SUM(CASE ... 1 ... 0)。我希望這是有道理的。

+0

我在postgresql中檢查。看起來不錯。 – 2010-06-27 08:42:47

+0

謝謝。你回答是我需要。 – 2010-06-27 08:54:41

2

請嘗試以下操作。您可能需要根據您的RDBMS修改日期函數。我假設MySQL,但其餘的應該是通用SQL。

SELECT doctors.name, monthly.average, monthly.month 
FROM doctors JOIN (
    SELECT AVG(cost), MONTH(visit_date) AS month FROM visits 
    WHERE YEAR(visit_date) GROUP BY MONTH(visit_date) 
) AS monthly ON doctors.id = visits.id_doc 

注意,這可能只包括訪問醫生的月份。因此,您可能需要使用IFNULLCOALESCE清理輸出。

1

你可以很容易地做到這一點 - 但它會在一個單獨的行中列出每個月的費用。如果你想在同一行的成本,你可以使用一個樞軸語句。這是SQL 2008如果你需要樞軸我們可以做的吧。如果有一個性能問題使用範圍掃描的日期,而不是使用日期部分

select d.name,datepart(month,v.visit_date) as month, 
avg(v.cost) as avgcost 
from visits as v inner join 
doctors as d on v.id_doc=d.id 
and datepart(year,v.visit_date)=2010 
group by d.name,datepart(month,v.visit_date)