简体   繁体   English

SQL显示两个日期之间的月数和年数

[英]SQL Show Number of Months and Years Between Two Dates

I have a table that shows the start date and the end date for a product. 我有一张表,显示产品的开始日期和结束日期。 I have the total value and the product name in the table. 我在表中有总价值和产品名称。 I would like to be able to show the months and years between the two dates while including the product name and the average of the value over the time period. 我希望能够显示两个日期之间的月份和年份,同时包括产品名称和该时间段内的平均值。 I have been trying to work with a query that solves the issue for a single product. 我一直在尝试使用一个查询来解决单个产品的问题。 I need the result to show across multiple products. 我需要将结果显示在多个产品上。 I'm getting an error saying that I cannot query more than one item in the sub query. 我收到一条错误消息,说我不能在子查询中查询多个项目。 Is it possible to get the result I'm looking for? 是否可以得到我想要的结果? Thank you for your help. 谢谢您的帮助。 It's greatly appreciated. 非常感谢。

SQL to display both month and year between two dates SQL在两个日期之间显示月份和年份

Example of Product Data 产品数据示例

    Product    Value Start Date End Date
    Widget A    100 1/1/2012    5/1/2013
    Widget B    500 2/1/2010    6/1/2012

Desired Results 所需结果

    Product     Date       Month Year    Value
    Widget A    1/1/2012    Jan 2012     5.88 
    Widget A    2/1/2012    Feb 2012     5.88 
    Widget A    3/1/2012    Mar 2012     5.88 
    Widget A    4/1/2012    Apr 2012     5.88 
    Widget A    5/1/2012    May 2012     5.88 
    Widget A    6/1/2012    Jun 2012     5.88 
    Widget A    7/1/2012    Jul 2012     5.88 
    Widget A    8/1/2012    Aug 2012     5.88 
    Widget A    9/1/2012    Sep 2012     5.88 
    Widget A    10/1/2012   Oct 2012     5.88 
    Widget A    11/1/2012   Nov 2012     5.88 
    Widget A    12/1/2012   Dec 2012     5.88 
    Widget A    1/1/2013    Jan 2013     5.88 
    Widget A    2/1/2013    Feb 2013     5.88 
    Widget A    3/1/2013    Mar 2013     5.88 
    Widget A    4/1/2013    Apr 2013     5.88 
    Widget A    5/1/2013    May 2013     5.88 
    Widget B    2/1/2010    Feb 2010     17.24 
    Widget B    3/1/2010    Mar 2010     17.24 
    Widget B    4/1/2010    Apr 2010     17.24 
    Widget B    5/1/2010    May 2010     17.24 
    Widget B    6/1/2010    Jun 2010     17.24 
    Widget B    7/1/2010    Jul 2010     17.24 
    Widget B    8/1/2010    Aug 2010     17.24 
    Widget B    9/1/2010    Sep 2010     17.24 
    Widget B    10/1/2010   Oct 2010     17.24 
    Widget B    11/1/2010   Nov 2010     17.24 
    Widget B    12/1/2010   Dec 2010     17.24 
    Widget B    1/1/2011    Jan 2011     17.24 
    Widget B    2/1/2011    Feb 2011     17.24 
    Widget B    3/1/2011    Mar 2011     17.24 
    Widget B    4/1/2011    Apr 2011     17.24 
    Widget B    5/1/2011    May 2011     17.24 
    Widget B    6/1/2011    Jun 2011     17.24 
    Widget B    7/1/2011    Jul 2011     17.24 
    Widget B    8/1/2011    Aug 2011     17.24 
    Widget B    9/1/2011    Sep 2011     17.24 
    Widget B    10/1/2011   Oct 2011     17.24 
    Widget B    11/1/2011   Nov 2011     17.24 
    Widget B    12/1/2011   Dec 2011     17.24 
    Widget B    1/1/2012    Jan 2012     17.24 
    Widget B    2/1/2012    Feb 2012     17.24 
    Widget B    3/1/2012    Mar 2012     17.24 
    Widget B    4/1/2012    Apr 2012     17.24 
    Widget B    5/1/2012    May 2012     17.24 
    Widget B    6/1/2012    Jun 2012     17.24 

You need to cross join to a numbers/dates table. 您需要交叉连接到数字/日期表。

If you don't have one however they are relatively inexpensive to create on the fly using a system table and ROW_NUMBER() 如果您没有,则使用系统表和ROW_NUMBER()即时创建它们相对便宜。

WITH Product AS
(   SELECT  Product, 
            Value = CAST(Value AS DECIMAL(10, 2)), 
            StartDate = CAST(StartDate AS DATE), 
            EndDate = CAST(EndDate AS DATE)
    FROM    (VALUES
                ('Widget A', 100, '20120101', '20130501'),
                ('Widget b', 500, '20100201', '20120601')
            ) t (Product, Value, StartDate, EndDate)
), Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  p.Product,
        d.[Date],
        MonthYear = LEFT(DATENAME(MONTH, d.[Date]), 3) + ' ' + DATENAME(YEAR, d.[Date]), 
        Value = CAST(p.Value / (1 + DATEDIFF(MONTH, p.StartDate, p.EndDate)) AS DECIMAL(5, 2))
FROM    Product p
        CROSS JOIN Numbers n
        OUTER APPLY (SELECT Date = DATEADD(MONTH, n.Number, p.StartDate)) d
WHERE   d.[Date] <= p.EndDate
ORDER BY p.Product, [Date];

Example on SQL Fiddle SQL小提琴示例

For some further reading on generating and using a numbers/dates table, both static and on the fly, take a look at this series: 有关静态和即时生成和使用数字/日期表的更多信息,请阅读以下系列:

Step one, get a list of dates. 第一步,获取日期列表。 The monthly dates in your output have to come from somewhere ...that's how SQL works. 输出中的每月日期必须来自某处 ...这就是SQL的工作方式。 Creating and maintaining a "calendar table" is very common, but there are other ways too. 创建和维护“日历表”非常普遍,但是还有其他方法。

CREATE TABLE months ([Date] date)
--Populate table with a list of first-of-months

SELECT
  p.[Product],
  m.[Date],
  LEFT(DATENAME(month,m.[Date]),3) AS [Month]
  YEAR(m.[Date]) AS [Year]
  p.[Value]/(DATEDIFF(month,p.[Start Date],p.[End Date])+1) AS [Value]
FROM months m
INNER JOIN products p ON (m.[Date] BETWEEN p.[Start Date] AND p.[End Date])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM