所以我有一个带有参数的表值函数:
SampleProcedure(@date,@par1,@par2,@par3)
日期变量是INT,例如:
@date int = 20170102
我想做的是迭代直到EOF或特定的,预定义的date,因此@date变量应在上一次迭代完成后更改。其他参数没有改变。
我应该采取什么方法?我想知道是否应该使用游标,但目前我还不太了解-如果有人在此示例中向我解释了它们(将日期迭代为整数),我将不胜感激。
编辑:
更具体的情况:
我有GetDailyUsageReal和GetDailyUsageForecast存储过程。
GetDailyUsageReal(@ date,@ par1,@ par2)
GetDailyUsageForecast(@ date,@ par1,@ par2)
我的输入:
DECLARE @date int = 20170102,
@par1 INT = 4000,
@par2 INT = 1,
;WITH CTE as (SELECT Hour, SUM(CAST(UsReal AS DECIMAL(19, 6))) / 1000000 as Real, Day
FROM GetDailyUsageReal(@date,@par1,@par2)
Group BY Hour,Day),
CTE2 as (SELECT Hour, SUM(CAST(UsForecast AS DECIMAL(19, 6))) / 1000000 as Forecast, Day
FROM GetDailyUsageForecast(@date,@par1,@par2)
Group BY Hour,Day)
SELECT cte.Hour, Real, cte2.Forecast , cte.Day
FROM CTE
JOIN CTE2 on cte.hour=cte2.hour AND cte.day=cte2.day
ORDER BY cte.hour
输出为:
+------+------+----------+----------+--+
| Hour | Real | Forecast | Day | |
+------+------+----------+----------+--+
| 1 | 10 | 12 | 20170102 | |
| 5 | 24 | 23 | 20170102 | |
| 7 | 24 | 22 | 20170102 | |
| 8 | 27 | 27 | 20170102 | |
| 9 | 26 | 21 | 20170102 | |
| 10 | 21 | 21 | 20170102 | |
| 11 | 11 | 12 | 20170102 | |
| 12 | 25 | 24 | 20170102 | |
| 13 | 17 | 18 | 20170102 | |
| 14 | 18 | 19 | 20170102 | |
| 15 | 26 | 25 | 20170102 | |
| 16 | 22 | 21 | 20170102 | |
| 17 | 23 | 23 | 20170102 | |
| 18 | 24 | 23 | 20170102 | |
| 19 | 19 | 18 | 20170102 | |
| 20 | 10 | 11 | 20170102 | |
| 21 | 11 | 13 | 20170102 | |
| 22 | 18 | 16 | 20170102 | |
| 23 | 19 | 17 | 20170102 | |
| 24 | 11 | 13 | 20170102 | |
+------+------+----------+----------+--+
我想要得到的基本上是接下来几天的输出,比如说直到2019年(我的数据库中甚至有一些2019年的数据)。
所以我需要的是日期的迭代。我无权将@date数据类型更改为DATE。
@ EDIT2:
我的预期输出:
+------+------+----------+----------+--+
| Hour | Real | Forecast | Day | |
+------+------+----------+----------+--+
| 1 | 10 | 12 | 20170102 | |
| 5 | 24 | 23 | 20170102 | |
| 7 | 24 | 22 | 20170102 | |
| 8 | 27 | 27 | 20170102 | |
| 9 | 26 | 21 | 20170102 | |
| 10 | 21 | 21 | 20170102 | |
| 11 | 11 | 12 | 20170102 | |
| 12 | 25 | 24 | 20170102 | |
| 13 | 17 | 18 | 20170102 | |
| 14 | 18 | 19 | 20170102 | |
| 15 | 26 | 25 | 20170102 | |
| 16 | 22 | 21 | 20170102 | |
| 17 | 23 | 23 | 20170102 | |
| 18 | 24 | 23 | 20170102 | |
| 19 | 19 | 18 | 20170102 | |
| 20 | 10 | 11 | 20170102 | |
| 21 | 11 | 13 | 20170102 | |
| 22 | 18 | 16 | 20170102 | |
| 23 | 19 | 17 | 20170102 | |
| 24 | 11 | 13 | 20170102 | |
| 1 | 15 | 14 | 20170103 | |
| 5 | 18 | 11 | 20170103 | |
| 7 | 26 | 44 | 20170103 | |
| 8 | 21 | 33 | 20170103 | |
| 9 | 22 | 12 | 20170103 | |
| 10 | 21 | 21 | 20170103 | |
| 11 | 11 | 12 | 20170103 | |
| 12 | 15 | 12 | 20170103 | |
| 13 | 17 | 18 | 20170103 | |
| 14 | 18 | 19 | 20170103 | |
| 15 | 26 | 25 | 20170103 | |
| 16 | 22 | 21 | 20170103 | |
| 17 | 23 | 23 | 20170103 | |
| 18 | 24 | 23 | 20170103 | |
| 19 | 19 | 18 | 20170103 | |
| 20 | 10 | 11 | 20170103 | |
| 21 | 11 | 13 | 20170103 | |
| 22 | 18 | 16 | 20170103 | |
| 23 | 19 | 17 | 20170103 | |
| 24 | 11 | 13 | 20170103 | |
+------+------+----------+----------+--+
我只想从选定范围之间的日期,或从选定日期到文件结束的范围中的日期获得值-数据库中基于该天的最后一行(因此,最后一天可以是例如20210131)。我想将它们放在一个结果表中,如上所示。
@EDIT更改后:
输出:
+------+-----------+-----------+----------+
| Hour | Real | Forecast | Workdate |
+------+-----------+-----------+----------+
| 20 | 11.831587 | 15.140129 | 20170101 |
| 21 | 11.659364 | 15.003950 | 20170101 |
| 22 | 11.111199 | 14.736179 | 20170101 |
| 23 | 11.075579 | 14.812968 | 20170101 |
| NULL | NULL | NULL | NULL |
| 1 | 9.930323 | 12.856905 | 20170102 |
| 2 | 9.826946 | 12.741908 | 20170102 |
+------+-----------+-----------+----------+
答案 0 :(得分:0)
@openshac建议有效。您应该将日期存储为DATE数据类型,并使用StartDate / EndDate它将使查询变得更容易。看看是否可以替换:
DECLARE @DATE DATE ='20170102'
与
DECLARE @StartDate DATE ='20170102'
DECLARE @EndDate DATE ='20180102'
答案 1 :(得分:0)
@Pejczi,我已经为您完成了此逻辑。您需要CTE来构建您感兴趣的所有日期。然后将表函数与外部Apply结合使用-这样可以确保将有效日期传递给函数,从而返回每个日期的小时和预测/实际列。 让我知道怎么回事:
DECLARE @StartDate DATE='20170101'
DECLARE @EndDate DATE='20180601'--current_timestamp
DECLARE @Dates TABLE(
Workdate DATE Primary Key
)
;WITH Dates AS(
SELECT Workdate=@StartDate
UNION ALL
SELECT CurrDate=DateAdd(DAY,1,Workdate) FROM Dates WHERE Workdate<@EndDate
)
SELECT *
FROM
Dates D
OUTER APPLY
(
SELECT Hour, SUM(CAST(UsForecast AS DECIMAL(19, 6))) / 1000000 as Real, Day as WorkDate
FROM GetDailyUsageReal(CONVERT(CHAR(8),D.Workdate,112),@par1,@par2)
GROUP BY
Hour,Day
)R
OUTER APPLY
(
SELECT Hour, SUM(CAST(UsForecast AS DECIMAL(19, 6))) / 1000000 as Forecast, Day as WorkDate
FROM GetDailyUsageForecast(CONVERT(CHAR(8),D.Workdate,112),@par1,@par2)
GROUP BY
Hour,Day
)F
ORDER BY
d.Workdate
option (maxrecursion 0);
答案 2 :(得分:0)
此版本在CTE日期上进行了扩展,并增加了“小时”列,因此您可以在“小时”上加入实/预测表功能。
DECLARE @StartDate DATETIME='20170101'
DECLARE @EndDate DATETIME='20170201'--current_timestamp
DECLARE @Dates TABLE(
Workdate DATE Primary Key
)
;WITH Dates AS(
SELECT Workdate=@StartDate,WorkHour=DATEPART(HOUR,@StartDate)+1
UNION ALL
SELECT CurrDate=DateAdd(HH,1,Workdate),DATEPART(HOUR,DateAdd(HH,1,Workdate))+1 FROM Dates WHERE Workdate<@EndDate
)
SELECT Workdate=CAST(Workdate AS date),WorkHour
FROM
Dates D
OUTER APPLY
(
SELECT Hour, SUM(CAST(UsForecast AS DECIMAL(19, 6))) / 1000000 as Real, Day as WorkDate
FROM GetDailyUsageReal(CONVERT(CHAR(8),D.Workdate,112),@par1,@par2) R
WHERE R.Hour=D.WorkHour
GROUP BY
Hour,Day
)R
OUTER APPLY
(
SELECT Hour, SUM(CAST(UsForecast AS DECIMAL(19, 6))) / 1000000 as Forecast, Day as WorkDate
FROM GetDailyUsageForecast(CONVERT(CHAR(8),D.Workdate,112),@par1,@par2) F
WHERE F.Hour=D.WorkHour
GROUP BY
Hour,Day
)F
option (maxrecursion 0);