【问题标题】:Assigning values for [Month] parameter in a stored procedure在存储过程中为 [Month] 参数赋值
【发布时间】:2016-01-22 16:04:05
【问题描述】:

我有一个存储过程,它的输出是一个包含 [Year] 和 [Month] 列以及许多其他列的表。我还创建了四个参数:@SYear、@SMonth、@EYear、@EMonth。 [year] 的不同之处是 2015 年和 2016 年。在月份列中,我在 2015 年有几个月,如 2、3、5、7、8 等,在 2016 年有 1,2 个月。现在我想分配从年和月列到参数的值。如果是年份,我可以将其分配为(@SYear 和@EYear 之间的[Year])。但是当谈到月份时,如果我分配([Month] BETWEEN @SMonth AND @EMonth),问题实际上是 2015 年的第 5 个月小于 2016 年的第 1 个月,但由于 sql 将 [Month] 作为整数 5 是大于 1.,所以它不起作用。如果我选择@SYear = 2015、@SMonth = 5、@EYear = 2015、@EMonth = 7,它会起作用。

请提出一种将月份列分配给开始和结束月份参数的可能方法。

顺便说一句,@S 是开始 @E 是结束。

希望我足够清楚,让你们理解这个问题,如果有人不明白,请告诉我。

谢谢。

编辑:

在这里,当我选择开始年份、开始月份和结束年份、结束月份作为参数时,我应该从表格中获取结果。

【问题讨论】:

  • 请提供您的代码和预期结果。提前致谢。
  • 您想通过 BETWEEN 找到什么?您对“2015 年第 5 个月和 2016 年第 1 个月”的预期结果是什么?
  • 这就是为什么您应该将日期时间值存储为日期时间。当您在自己的列中将月份和年份拆分为整数时,这将成为一个真正的挑战。如果可能的话,将数据类型更改为 datetime 并且这个问题不是问题。
  • 我正在尝试检索选定日期之间的数据。就像一个ssrs报告参数。 @凯尔
  • @SeanLange 我只需要开始年月和结束年月作为参数,这就是问题所在。实际上我必须用存储的过程构建一个 ssrs 报告

标签: sql sql-server sql-server-2008


【解决方案1】:

不是答案,长评论

这很难看,我知道,如果你不能使用 DATEFROMPARTS() 类似这样的东西可能会起作用(或转换字符串)

SELECT *

FROM table1 t

WHERE
DATEADD(mm, t.Month -1, dateadd(yy,t.Year-1900,'19000101'))
BETWEEN
DATEADD(mm, @sMonth -1, dateadd(yy,@sYear-1900,'19000101'))
AND
DATEADD(mm, @eMonth -1, dateadd(yy,@eYear-1900,'19000101'))

【讨论】:

  • 它没有用。它正在拉取所有记录而不是指定的参数。
  • 如果你运行这个SELECT DATEADD(mm, @eMonth -1, dateadd(yy,@eYear-1900,'19000101')) as endDate会发生什么
  • 我得到所有空值
  • declare @eYear int, @eMonth int; set @eYear=2015; set @eMonth=7; select DATEADD(mm, @eMonth -1, dateadd(yy,@eYear-1900,'19000101')); 不为空,是日期时间 20150701 00:00:00
【解决方案2】:

这取代了我之前的答案,以便完全回答问题。事实证明,这是比看起来要困难得多的事情之一。我真的认为下面的答案 #2(创建计算字段)将是可靠的后备答案,但事实证明您不能在 PERSISTED 字段中使用带有 DATE 类型的 CAST() ,从而增加了复杂性。

这是答案 1,如果...则使用它

  • 您需要经常进行此查询
  • 您有大量数据,需要索引
  • 您不介意更改表结构

“正确的方法”是通过添加包含实际 MONTH/YEAR 的字段和当天的虚拟“1st”来添加作为实际 DATE 的列。将其存储为 DATE,然后将其用于查询。这可以被索引,并且会尽可能快。

这是答案 2,如果...则使用它

  • 您需要经常进行此查询
  • 您的数据很少,因此不需要索引
  • 您不想更改表结构

您可以使用以下任一方法在表上创建计算字段。这样,每当您编写查询时,您就可以使用日期字段并且生活很简单——除非您不会点击索引。

ALTER TABLE table1
ADD THE_DATE1 AS CONVERT(VARCHAR(4), THE_YEAR ) + '-' + CONVERT(VARCHAR(2), THE_MONTH) + '-01'

ALTER TABLE table1
ADD THE_DATE2 AS DATEADD(mm, THE_MONTH -1, dateadd(yy,THE_YEAR-1900,'19000101'))

ALTER TABLE table1 -- SQL212+
ADD THE_DATE3 AS DATEFROMPARTS(THE_YEAR, THE_MONTH,  1)

这是答案 3,如果...则使用它

  • 您需要经常进行此查询
  • 您有大量数据,确实需要索引
  • 你不介意疯狂的查询

您可以使用疯狂的 WHERE 语句来获取数据。下面有两个版本,第二个版本包含一些 AND 语句,可以帮助 SQL SERVER 命中某些索引(因为 SQL 不喜欢在 WHERE 语句中有一堆 OR 运算符)。

DECLARE @table1 AS TABLE (
         ID INT ,
         THE_YEAR INT ,
         THE_MONTH INT ,
         THE_MONEY INT
        )

INSERT  INTO @table1
VALUES  ( 1, 2015, 5, 20 ),
        ( 2, 2015, 7, 50 ),
        ( 3, 2015, 9, 8 ),
        ( 4, 2015, 10, 60 ),
        ( 5, 2015, 12, 30 ),
        ( 6, 2016, 1, 90 ),
        ( 7, 2016, 2, 120 ),
        ( 8, 2017, 1, 220 ), -- Added for testing
        ( 9, 2017, 2, 320 )  -- Added for testing

DECLARE @START_YEAR INT = 2015;
DECLARE @START_MONTH INT = 7;

DECLARE @STOP_YEAR INT = 2015;
DECLARE @STOP_MONTH INT = 10;

-- QUERY THAT ANSWERS YOUR QUESTION

SELECT  *
FROM    @table1
WHERE   (
            ( @START_YEAR <> @STOP_YEAR AND THE_YEAR  = @START_YEAR AND THE_MONTH >= @START_MONTH )
            OR 
            ( @START_YEAR <> @STOP_YEAR AND THE_YEAR > @START_YEAR AND THE_YEAR < @STOP_YEAR )
            OR 
            ( @START_YEAR <> @STOP_YEAR AND THE_YEAR  = @STOP_YEAR  AND THE_MONTH <= @STOP_MONTH )
            OR 
            -- Handle when Start/Stop year are the same
            ( @START_YEAR  = @STOP_YEAR  AND THE_MONTH >= @START_MONTH AND THE_MONTH <= @STOP_MONTH )
        )
ORDER BY THE_YEAR ,
        THE_MONTH


-- QUERY THAT ANSWERS YOUR QUESTION, with INDEX optimizations
-- because once you have a bunch of data, this may help you hit on an index.
SELECT  *
FROM    @table1
WHERE   THE_YEAR >= @START_YEAR   -- Will hit an INDEX if you have one on THE_YEAR
        AND THE_YEAR <= @STOP_YEAR -- Will hit an INDEX if you have one on THE_YEAR
        AND
        (
                ( @START_YEAR <> @STOP_YEAR AND THE_YEAR  = @START_YEAR AND THE_MONTH >= @START_MONTH )
                OR 
                ( @START_YEAR <> @STOP_YEAR AND THE_YEAR > @START_YEAR AND THE_YEAR < @STOP_YEAR )
                OR 
                ( @START_YEAR <> @STOP_YEAR AND THE_YEAR  = @STOP_YEAR  AND THE_MONTH <= @STOP_MONTH )
                OR 
                -- Handle when Start/Stop year are the same
                ( @START_YEAR  = @STOP_YEAR  AND THE_MONTH >= @START_MONTH AND THE_MONTH <= @STOP_MONTH )
            )
ORDER BY THE_YEAR ,
        THE_MONTH

【讨论】:

  • 我一定会试试这个,让你知道它是否有效。非常感谢您的宝贵时间。
  • 这看起来如果@START_YEAR@STOP_YEAR是同一年会有问题;例如,2015 年 6 月到 2015 年 9 月之间。我认为它会检索全年的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 2017-10-06
  • 2011-07-16
  • 2018-10-31
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多