我有一个存储过程,其输出是一个包含[Year]和[Month]列以及许多其他列的表。我还创建了四个参数:@SYear,@ SMonth,@EYear,@ emonth。 [年份]的不同之处是2015年和2016年。在月份专栏中,我有几个月的时间,如2015年的2,3,5,7,8等,2016年的1,2。现在我想分配从年份和月份列到参数的值。如果是一年,我可以将其指定为([年] @SYear和@EYear之间)。但是当我指定月份([月] BETWEEN @SMonth和@EMonth)时,问题实际上是2015年的第5个月不到2016年的第1个月,但是因为sql以[月]为整数5是大于1.,所以它不起作用。如果我选择@SYear = 2015,@ SMonth = 5,@ yaye = 2015,@ emonth = 7就可以了。
请建议一种可能的方法,将月份列分配给开始和月末参数。
BTW @S开始@E结束了。
希望我很清楚你们能够理解这个问题,如果有人不理解,请告诉我。
谢谢。在这里,当我选择开始年份,开始月份和结束年份,结束月份作为参数时,我应该从表格中获得结果。
答案 0 :(得分:0)
不是答案,长评论
这是丑陋的,我知道,如果你不能使用DATEFROMPARTS()这样的东西可能会起作用(或演员字符串)
onProgressUpdate
答案 1 :(得分:0)
这取代了之前的答案,以便完全回答这个问题。事实证明这是比它应该更难的事情之一。我真的认为下面的答案#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