Mysql sql为每个月选择一条记录,记录总数为该月记录
我有一个数据库,其中有一个“约会表”和“服务表”。每个appt都有一个服务,每个服务都有一个价格。我想要的是一个查询,它将始终返回12行(每个月一行),并包含月appt的总和(基于它的服务id)。到目前为止,我已经:Mysql sql为每个月选择一条记录,记录总数为该月记录,mysql,sql,Mysql,Sql,我有一个数据库,其中有一个“约会表”和“服务表”。每个appt都有一个服务,每个服务都有一个价格。我想要的是一个查询,它将始终返回12行(每个月一行),并包含月appt的总和(基于它的服务id)。到目前为止,我已经: select sum(service_price) as monthly_total, year(appt_date_time) as year, monthname(appt_date_time) as month from appt_tbl
select sum(service_price) as monthly_total,
year(appt_date_time) as year,
monthname(appt_date_time) as month
from appt_tbl
join services_tbl on appt_tbl.service_id = services_tbl.service_id
group by month(appt_date_time),
year(appt_date_time)
order by month(appt_date_time) asc;
目前,这会返回类似以下内容:
+---------------+------+-------+
| monthly_total | year | month |
+---------------+------+-------+
| 120.00 | 2012 | July |
+---------------+------+-------+
问题是,如果一个月没有任何appt,我就不会在查询中返回该月。我希望那个月有一个记录,只要它的“月总”等于零
以下是我希望查询返回的内容:
+---------------+------+-------+
| monthly_total | year | month |
+---------------+------+-------+
| 0.00 | 2012 | Jan |
+---------------+------+-------+
| 0.00 | 2012 | Feb |
+---------------+------+-------+
| 0.00 | 2012 | March |
+---------------+------+-------+
| 0.00 | 2012 | April |
+---------------+------+-------+
| 0.00 | 2012 | May |
+---------------+------+-------+
| 0.00 | 2012 | June |
+---------------+------+-------+
| 120.00 | 2012 | July |
+---------------+------+-------+
| 0.00 | 2012 | August|
+---------------+------+-------+
| 0.00 | 2012 | Sept |
+---------------+------+-------+
| 0.00 | 2012 | Oct |
+---------------+------+-------+
| 0.00 | 2012 | Nov |
+---------------+------+-------+
| 0.00 | 2012 | Dec |
+---------------+------+-------+
有什么想法吗?您的思路是正确的,只需将查询结果左键连接到一个monthnames表中即可。然后,结果中存在的名称将返回一个匹配项,对于结果中不存在的月份,将返回一个
NULL
。一个COALESCE
或NVL
或CASE
构造,不管你喜欢什么,都可以用来将NULL
转换成一个直接的0
您不需要创建一个真正的月份表,您可以通过使用一个内联视图(只需一个生成所有月份数据的查询)来获取
select months.month, coalesce(appts.monthly_total, 0) monthly_total
from (
select 'January' as month
union all select 'February'
union all select 'March'
...etc...
union all select 'December'
) months
left join (
select sum(service_price) as monthly_total,
monthname(appt_date_time) as month
from appt_tbl
inner join services_tbl
on appt_tbl.service_id = services_tbl.service_id
where appt_date_time between '2012-01-01 00:00:00'
and '2012-12-31 23:59:59'
group by month(appt_date_time)
) appts
on months.month = appts.month
对于某一年的每一次返回,请查看WHERE条件。我正在计算appt_date_time是日期时间还是时间戳。您不想写YEAR(appt_date_time)=2012,因为这会破坏在该列上使用索引的机会(我假设该列显示为索引中的第一列)。通过使用BETWEEN…AND与literalDateTimes进行比较,您可以获得一个非常有效的查询,满足要求
此外,如果您在
month(appt\u date\u time)上groupby
,mysql将确保结果也按月份升序排序。因此,无需通过
单独订购。联合查询的“分支”顺序也将由mysql保留。试试这个,它会对您有用。您所需要做的就是创建一个查找表,以获得更好的方法
CREATE TABLE MONTHS(MON CHAR(3))
INSERT INTO MONTHS
SELECT 'Jan' UNION ALL
SELECT 'Feb' UNION ALL
SELECT 'Mar' UNION ALL
SELECT 'Apr' UNION ALL
SELECT 'May' UNION ALL
SELECT 'Jun' UNION ALL
SELECT 'Jul' UNION ALL
SELECT 'Aug' UNION ALL
SELECT 'Sep' UNION ALL
SELECT 'Oct' UNION ALL
SELECT 'Nov' UNION ALL
SELECT 'Dec'
CREATE TABLE Appointments(App int, Year int, Month CHAR(3))
INSERT INTO Appointments
SELECT 120,2012,'Jul' UNION ALL
SELECT 120,2013,'Apr'
SELECT sum(isnull(App,0)) monthly_total, b.Mon , b.Year FROM Appointments a
RIGHT JOIN (SELECT DISTINCT Year,Mon FROM Appointments CROSS JOIN MONTHS) b
ON a.Month=b.MON AND a.Year=b.Year
GROUP BY b.Mon,b.Year
您是否尝试过left join??“我想要的是一个查询,它将始终返回12行(每个月一行)”<您的原始查询组按年份和月份排序。你的意思是:每年12行,还是你真的想把所有的月份累加起来,不管哪一年都得到12行?如果你添加表
months
,然后用服务价格加入months,它会帮你完成这项工作。我想在没有月台的情况下做这件事。还有,布文说的。如果约会表中的每个日期都有一行,或者至少每个月都有一行,则左联接应确保您在结果中获得所有月份。尝试了左联接,没有骰子。在我的应用程序中,新用户的表中不会有任何应用程序,因此每个月的初始报告应仅为0(报告将以一年作为上下文运行,但这在我的查询中尚未表示)@roland您的正确答案,我希望总共12行,一年中每个月一行(假设年=2012),感谢您指出这一点!我想我和你意见一致。我创建了一个名为“months\u tbl”的表。让我不高兴的是“合并(appts.monthly_total,0)monthly_total”appt_tbl中没有“monthly_total”字段。这是对左侧连接选择状态的引用吗?顺便说一句,这真是太棒了……是的,我写道:left join(…bla…)appts,所以最后一个appts是括号之间整个查询的别名。所以本地名称appts指的是那个子查询,而在外部查询appts.monthly\u total指的是那个sum(service\u price)表达式,因为在内部查询中它被赋予了monthly\u total别名。哇,我现在看到了。非常聪明,让我来试一试。回答得很好,效果很好。谢谢你快速、彻底的回答!