从2个日期参数获取数月之间的数量

时间:2016-02-19 13:11:11

标签: sql-server sql-server-2012

我有一张表格,用于存储财政年度从4月1日开始到明年3月31日结束的公司的预算数量。

我有这个查询来提取特定月份的数据。

SELECT SUM(T1.U_Quantity) AS 'YTDBOwnMadeTea'
      FROM [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA] T0
INNER JOIN [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA_ROW] T1 
      ON T0.DocEntry = T1.DocEntry
WHERE T1.U_Month = DATENAME(MONTH, '2015-04-01') AND T0.U_Source = 'NTEL'

现有报告采用两个参数,即开始日期和结束日期。 (输入日期时间)

下表:月份列的类型为nvarchar。

enter image description here

当用户输入StartDate和EndDate时,如何修改查询,例如 2015年5月1日和2015年7月31日,我将得到12640的数量结果。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:4)

你可以用几种方法来做到这一点。

一种方法是使用PARSE。像这样。

SELECT SUM(T1.U_Quantity) AS 'YTDBOwnMadeTea'
      FROM [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA] T0
INNER JOIN [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA_ROW] T1 
      ON T0.DocEntry = T1.DocEntry
WHERE PARSE((T1.U_Month + CONVERT(VARCHAR(4),YEAR(CURRENT_TIMESTAMP))) as datetime) BETWEEN @StartDate AND @EndDate
    AND T0.U_Source = 'NTEL'

另一种方法是使用数字表将月份名称映射到月份数字并在查询中使用它。

;WITH CTE AS (
SELECT 1 as rn UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
),
MonthMap AS
(
SELECT ROW_NUMBER()OVER(ORDER BY rn ASC) as monthnumber FROM CTE
)
SELECT monthnumber,DATENAME(MONTH,DATEFROMPARTS(2016,monthnumber,1)) FROM MonthMap;

然后将它与您的月份表一起加入。

;WITH CTE AS (
SELECT 1 as rn UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
),
MonthMap AS
(
SELECT ROW_NUMBER()OVER(ORDER BY rn ASC) as monthnumber FROM CTE
)
SELECT SUM(T1.U_Quantity) AS 'YTDBOwnMadeTea'
      FROM [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA] T0
INNER JOIN [SL_NTEL_DB_LIVE].[dbo].[@U_BUDG_MADETEA_ROW] T1 
      ON T0.DocEntry = T1.DocEntry
INNER JOIN MonthMap M ON T1.U_Month = DATENAME(MONTH,DATEFROMPARTS(2016,monthnumber,1))
WHERE M.monthnumber BETWEEN DATEPART(MONTH,@StartDate) AND DATEPART(MONTH,@EndDate)
AND T0.U_Source = 'NTEL';

您应该比较两种表现方法。 PARSE使用起来比较简单,但很难正确编制索引。

在单独的备注上,您应避免将日期或日期部分存储为月份名称,因为这些会占用更多存储空间(因为您使用NVARCHAR时更多),以及难以有效使用。