我有一张销售表:
id_item, quantity, date_time
我需要的是将一个月内售出的商品加总,并将其除以选定月份的月份之日。
示例 - 用户选择10月1日到12月31日的日期。我需要显示items_sold / days_of_month:
Month Items sold Days of month Items/Day
Sep 25 30 0.83333
Oct 36 31 1.16
Dec 15 31 0.4838
我必须按种类指定。该类是从另一个名为Items的表中获得的。我使用dateformat dd/mm/yy
。
select
month(date_time),
sum(quantity) / (select(datepart(dd,getdate())))
from
sales v
join items a on v.id_item=a.id_item
where
a.kind='Kind of Item'
and cast(Convert(varchar(10), date_time, 112) as datetime)
between '01/10/2012' and '31/12/2012'
group by
month(date_time)
我的问题是选择几个月的日子,如何选择x个月并将每个月的总和(数量)除以每个月的天数?
我知道代码的这一部分只选择当月的日期:
(select(datepart(dd,getdate())))
答案 0 :(得分:4)
尝试使用此尺寸:
DECLARE
@FromDate datetime,
@ToDate date; -- inclusive
SET @FromDate = DateAdd(month, DateDiff(month, 0, '20121118'), 0);
SET @ToDate = DateAdd(month, DateDiff(month, 0, '20121220') + 1, 0);
SELECT
Year = Year(S.date_time),
Month = Month(S.date_time),
QtyPerDay =
Sum(s.quantity) * 1.0
/ DateDiff(day, M.MonthStart, DateAdd(month, 1, M.MonthStart))
FROM
dbo.Sales S
INNER JOIN dbo.Items I
ON S.id_item = I.id_item
CROSS APPLY (
SELECT MonthStart = DateAdd(month, DateDiff(month, 0, S.date_time), 0)
) M
WHERE
I.kind = 'Kind of Item'
AND S.date_time >= @FromDate
AND S.date_time < @ToDate
GROUP BY
Year(S.date_time),
Month(S.date_time),
M.MonthStart
它将选择由FromDate
和ToDate
部分包围的任何完整月份。如果* 1.0
列是整数,则quantity
部分是必需的,否则您将获得整数结果而不是小数结果。
一些风格的笔记:
请勿在列上使用字符串日期转换,以确保您获得整天。这将完全阻止使用任何索引,需要更多的CPU,而且还不清楚(样式112又做了什么!?!?)。要附上完整日期,请使用我在DateCol >= StartDate
和DateCol < OneMoreThanEndDate
查询中显示的内容。搜索“sargable”以了解一个非常关键的概念。一个非常安全且有价值的一般规则是永远不会在表达式中放置一个列,如果条件可以被重写以避免它。
您对表的别名很好,但是您应该在每个列的查询中使用这些别名,就像我在查询中所做的那样。我认识到别名V和A来自另一种语言所以它们在那里有意义 - 通常尝试使用与表名匹配的别名。
在对象上包含架构名称。不这样做不是一个巨大的禁忌,但有一定的好处,这是最好的做法。
当你提出一个问题时,解释所有逻辑是有帮助的,所以人们不必猜测或问你 - 如果你知道(例如)用户可以输入月中日期但你需要整整几个月请在你的问题中说明你需要做什么。
提供SQL服务器版本有助于我们了解所需的语法,因为之前的版本不那么具有表现力。通过告诉我们版本,我们可以为您提供最佳查询。
注意:将日期计算数学放入查询本身并没有错(而不是使用SET来完成)。但我想你会在存储过程中对此进行编码,如果是这样,使用SET就可以了。