SiteVisitID siteName visitDate
------------------------------------------------------
1 site1 01/03/2014
2 Site2 01/03/2014
3 site1 02/03/2014
4 site1 03/03/2014
5 site2 03/03/2014
6 site1 04/03/2014
7 site2 04/03/2014
8 site2 05/03/2014
9 site1 06/03/2014
10 site2 06/03/2014
11 site1 08/03/2014
12 site2 08/03/2014
13 site1 09/03/2014
14 site2 10/03/2014
有两个网站,每个网站都需要每月的访问条目,所以考虑到今天是2014年3月11日我们预计有22个参赛作品,但只有14个条目如此缺失8,有什么办法吗?在sql中我们可以提取缺少的日期条目
截至当月对网站的当天
siteName missingDate
-----------------------
site2 02/03/2014
site1 05/03/2014
site1 07/03/2014
site2 07/03/2014
site2 09/03/2014
site1 10/03/2014
site1 11/03/2014
site2 11/03/2014
这是我在逻辑和语法上错误的尝试
select
siteName, visitDate
from
SiteVisit not in (SELECT siteName, visitDate
FROM SiteVisit
WHERE Day(visitDate) != Day(CURRENT_TIMESTAMP)
AND Month(visitDate) = Month(CURRENT_TIMESTAMP))
注意:上面的数据和列是实际表的简化版
答案 0 :(得分:5)
我建议您使用table valued function
在两个选定日期之间的所有日子作为表格(Try it out in this fiddle):
CREATE FUNCTION dbo.GetAllDaysInBetween(@FirstDay DATETIME, @LastDay DATETIME)
RETURNS @retDays TABLE
(
DayInBetween DATETIME
)
AS
BEGIN
DECLARE @currentDay DATETIME
SELECT @currentDay = @FirstDay
WHILE @currentDay <= @LastDay
BEGIN
INSERT @retDays (DayInBetween)
SELECT @currentDay
SELECT @currentDay = DATEADD(DAY, 1, @currentDay)
END
RETURN
END
(我包括一个简单的表格设置,便于复制品测试)
CREATE TABLE SiteVisit (ID INT PRIMARY KEY IDENTITY(1,1), visitDate DATETIME, visitSite NVARCHAR(512))
INSERT INTO SiteVisit (visitDate, visitSite)
SELECT '2014-03-11', 'site1'
UNION
SELECT '2014-03-12', 'site1'
UNION
SELECT '2014-03-15', 'site1'
UNION
SELECT '2014-03-18', 'site1'
UNION
SELECT '2014-03-18', 'site2'
现在,您可以简单地查看当您知道&#34;边界日期时没有访问的日期&#34;比如:
SELECT
DayInBetween AS missingDate,
'site1' AS visitSite
FROM dbo.GetAllDaysInBetween('2014-03-11', '2014-03-18') AS AllDaysInBetween
WHERE NOT EXISTS
(SELECT ID FROM SiteVisit WHERE visitDate = AllDaysInBetween.DayInBetween AND visitSite = 'site1')
或者,如果您想知道未访问任何网站的所有日子,您可以使用此查询:
SELECT
DayInBetween AS missingDate,
Sites.visitSite
FROM dbo.GetAllDaysInBetween('2014-03-11', '2014-03-18') AS AllDaysInBetween
CROSS JOIN (SELECT DISTINCT visitSite FROM SiteVisit) AS Sites
WHERE NOT EXISTS
(SELECT ID FROM SiteVisit WHERE visitDate = AllDaysInBetween.DayInBetween AND visitSite = Sites.visitSite)
ORDER BY visitSite
请注意:您的表中似乎有一些重复(未规范化)siteName
应该真正进入一个单独的表格,并且只能从SiteVisit
引用
答案 1 :(得分:2)
如果你有一个&#39;日历表,这会变得更加简单。也就是说,这个表格包含您可能感兴趣的每个日期。
原因是SQL无法报告不存在的内容。您可以编写SQL以创建应该属于间隙的日期(例如此处的另一个答案),然后报告创建的日期。或者你可以将它们放在一个持久的日历表中。并且只是使用它,使SQL更简单,更频繁,然后更快,更快。
在类似的徒劳中,我假设您有一个维度表,其中包含可以访问的所有站点?如果是这样,那么你得到这样的东西......
SELECT
*
FROM
site
CROSS JOIN
calendar
LEFT JOIN
visit
ON visit.site_id = site.id
AND visit.visitDate = calendar.date
WHERE
calendar.date >= DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
AND calendar.date < GETDATE()
AND visit.visitDate IS NULL
答案 2 :(得分:2)
也许您可以将此作为起点:
-- Recursive CTE to generate a list of dates for the month
-- You'll probably want to play with making this dynamic
WITH Dates AS
(
SELECT
CAST('2014-03-01' AS datetime) visitDate
UNION ALL
SELECT
visitDate + 1
FROM
Dates
WHERE
visitDate + 1 < '2014-04-01'
)
-- Build a list of siteNames with each possible date in the month
, SiteDates AS
(
SELECT
s.siteName, d.visitDate
FROM
SiteVisitEntry s
CROSS APPLY
Dates d
GROUP BY
s.siteName, d.visitDate
)
-- Use a left anti-semi join to find the missing dates
SELECT
d.siteName, d.visitDate AS missingDate
FROM
SiteDates d
LEFT JOIN
SiteVisitEntry e /* Plug your actual table name here */
ON
d.visitDate = e.visitDate
AND
d.siteName = e.siteName
WHERE
e.visitDate IS NULL
OPTION
(MAXRECURSION 0)
答案 3 :(得分:0)
在这里,我正在实现用户定义的功能genrate
。
CREATE FUNCTION genrate(@FROM_date date,@to_date date)
RETURNS @tab table(missing date)
AS
BEGIN
;WITH cte AS
(
SELECT @FROM_date missing
UNION ALL
SELECT DATEADD(DAY,1,missing)
FROM cte
WHERE missing <@to_date
)
INSERT INTO @tab
SELECT *
FROM cte
WHERE missing NOT IN (@FROM_date, @to_date)
RETURN
END
使用该函数和数据集,我们将进行cross apply
来生成缺少的日期集。
SELECT user_No,
product_name,
amount,
b.missing AS Missing_date
FROM date_tab t
CROSS APPLY DBO.genrate(T.ORDER_DATE,T.DELIVERY) b