Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql sql为每个月选择一条记录,记录总数为该月记录_Mysql_Sql - Fatal编程技术网

Mysql sql为每个月选择一条记录,记录总数为该月记录

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

我有一个数据库,其中有一个“约会表”和“服务表”。每个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 
     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别名。哇,我现在看到了。非常聪明,让我来试一试。回答得很好,效果很好。谢谢你快速、彻底的回答!