需要SQL服务器查询优化方面的帮助,如下所示:
var date = "2001-05"
func stringToDate(_ date: String) -> Date? {
let df = DateFormatter()
df.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale!
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ"
return df.date(from: date)
}
print(stringToDate(date))
结果应如下:
enter declare @sDate datetime
declare @eDate datetime
SET @sDate = '2017-01-01'
SET @eDate = '2017-01-31'
SELECT
@sDate AS [StartDate],
DATEADD(day,6, @sDate) [ENDDATE],
SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
WHERE
(GS.[ModifiedDate] > @sDate)
AND
(GS.[ModifiedDate] <= DATEADD(day,6, @sDate))
UNION
SELECT
DATEADD(day,7, @sDate) AS [StartDate],
DATEADD(day,13, @sDate) [ENDDATE],
SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
WHERE
(GS.[ModifiedDate] > DATEADD(day,7, @sDate))
AND
(GS.[ModifiedDate] <= DATEADD(day,13, @sDate))
UNION
SELECT
DATEADD(day,14, @sDate) AS [StartDate],
DATEADD(day,20, @sDate) [ENDDATE],
SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
WHERE
(GS.[ModifiedDate] > DATEADD(day,7, @sDate))
AND
(GS.[ModifiedDate] <= DATEADD(day,20, @sDate))
UNION
SELECT
DATEADD(day,21, @sDate) AS [StartDate],
DATEADD(day,27, @sDate) [ENDDATE],
SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
WHERE
(GS.[ModifiedDate] > DATEADD(day,21, @sDate))
AND
(GS.[ModifiedDate] <= DATEADD(day,27, @sDate))
UNION
SELECT
DATEADD(day,27, @sDate) AS [StartDate],
@eDate [ENDDATE],
SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
WHERE
(GS.[ModifiedDate] > DATEADD(day,27, @sDate))
AND
(GS.[ModifiedDate] <= @eDate)
可能需要对每周数据使用CTE(公用表表达式),如此处所述
how to get the start and end dates of all weeks between two dates in SQL server?
StartDate ENDDATE rcOpen rcClosed
2017-01-01 00:00:00.000 2017-01-07 00:00:00.000 NULL NULL
2017-01-08 00:00:00.000 2017-01-14 00:00:00.000 NULL NULL
2017-01-15 00:00:00.000 2017-01-21 00:00:00.000 12 5
2017-01-22 00:00:00.000 2017-01-28 00:00:00.000 NULL NULL
2017-01-28 00:00:00.000 2017-01-31 00:00:00.000 NULL NULL
答案 0 :(得分:0)
如果您无法在数据库中添加Dates或Numbers表,那么使用您提到的CTE生成的派生表可能是最好的方法:
declare @sDate datetime,
@eDate datetime;
select @sDate = '2013-02-25',
@eDate = '2013-03-25';
;with cte as
(
select @sDate StartDate,
DATEADD(wk, DATEDIFF(wk, 0, @sDate), 6) EndDate
union all
select dateadd(ww, 1, StartDate),
dateadd(ww, 1, EndDate)
from cte
where dateadd(ww, 1, StartDate)<= @eDate
)
SELECT
CTE.StartDate
,CTE.EndDate
,SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen]
,SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM CTE
LEFT JOIN GS
ON CTE.StartDate < GS.[ModifiedDate]
AND CTE.EndDate >= GS.[ModifiedDate]
GROUP BY CTE.StartDate
,CTE.EndDate
ORDER BY CTE.StartDate
答案 1 :(得分:0)
此查询的性能优于递归CTE。
declare @sDate datetime = '2017-01-01';
declare @eDate datetime = '2017-01-31';
WITH X AS (
SELECT DISTINCT
DATEADD(DAY, - (DATEPART(WEEKDAY, [Dates])-1), [Dates]) [WeekStart]
, DATEADD(DAY, 7- (DATEPART(WEEKDAY, [Dates])), [Dates]) [WeekEnd]
FROM (
SELECT DISTINCT DATEADD(DAY , rn -1 , @sDate) [Dates]
FROM (
Select TOP (DATEDIFF(DAY, @sDate, @eDate))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) rn
FROM master..spt_values a
CROSS JOIN master..spt_values b
)a
) b
)
SELECT [WeekStart]
, [WeekEnd]
, SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen],
, SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM X
LEFT JOIN GS ON GS.[ModifiedDate] <= CTE.[WeekEnd]
AND GS.[ModifiedDate] >= CTE.[WeekStart]
答案 2 :(得分:0)
另一种方法
declare @sDate datetime
declare @eDate datetime
SET @sDate = '2017-01-01'
SET @eDate = '2017-01-31'
--A recursive CTE for fetching the weeks range
;WITH CTE AS
(
SELECT @sDate SDATE
, DATEADD(DD,6,@sDate) AS TO_DTE
UNION ALL
SELECT DATEADD(DD,1,TO_DTE)
, CASE
WHEN DATEADD(DD, 7, TO_DTE) > @eDate
THEN @eDate
ELSE DATEADD(DD, 7, TO_DTE)
END
FROM CTE
WHERE DATEADD(DD, 1, TO_DTE) <= @eDate
)
/* An Intermediate result of CTE to better understand
+-------------------------+-------------------------+
| SDATE | TO_DTE |
+-------------------------+-------------------------+
| 2017-01-01 00:00:00.000 | 2017-01-07 00:00:00.000 |
| 2017-01-08 00:00:00.000 | 2017-01-14 00:00:00.000 |
| 2017-01-15 00:00:00.000 | 2017-01-21 00:00:00.000 |
| 2017-01-22 00:00:00.000 | 2017-01-28 00:00:00.000 |
| 2017-01-29 00:00:00.000 | 2017-01-31 00:00:00.000 |
+-------------------------+-------------------------+
*/
SELECT CTE.SDATE
,CTE.TO_DTE
,SUM(CASE WHEN GS.[Status] = 'Open' THEN 1 ELSE 0 END) [rcOpen]
,SUM(CASE WHEN GS.[Status] = 'Closed' THEN 1 ELSE 0 END) [rcClosed]
FROM GS
JOIN CTE
ON GS.[ModifiedDate] > CTE.SDATE
AND GS.[ModifiedDate] <= CTE.TO_DTE
GROUP BY CTE.SDATE
,CTE.TO_DTE
ORDER BY CTE.SDATE
答案 3 :(得分:0)
$scope
在@iamdave中进行少量更改后,上面的回答将是正确答案
答案 4 :(得分:-1)
也许您可以使用UNION ALL
而不只是UNION
。