12个子查询的SQL问题

时间:2010-06-26 23:58:02

标签: sql task

存在这样的数据库模式: alt text http://img156.imageshack.us/img156/9017/2706.png

我需要写查询。

对于每位医生,我需要按月平均访问费用为2009年。 结果是(name_of_doctor,january,febriary,...,12月)

我知道如何用12子查询做到这一点。还有另一种更方便的方式吗?

3 个答案:

答案 0 :(得分: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 :(得分:1)

您可以轻松地执行以下操作 - 但它会在单独的行中列出每个月的成本。如果您希望在同一行上的成本,您可以使用数据透视表。如果您需要旋转,我们可以使用SQL 2008如果出现性能问题,请使用日期范围扫描,而不是使用datepart

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)

答案 2 :(得分: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​​将NULL计为0成本而不是折扣它们那么你可能需要做自己的averag - SUM(CASE ...成本... 0)/ SUM(CASE ... 1 ... 0)。我希望这是有道理的。