在我的表中,我有一个datetime列和一个标记列。如果在时间跨度内没有值,我想在时间跨度之前选择最新值。如果时间跨度中有值,我不想返回任何值。
我的查询具有以下输入参数:
@StartDate datetime
@EndDate datetime
最重要的查询结果:
我的问题,我创建了两个查询:
这个想法是SELECT [Values before the timespan] WHERE NOT EXISTS IN [Values in the timespan]
。
我试图加入这些查询以获得最终结果,但这是我努力的地方。
重播步骤(设置):
CREATE TABLE dbo.MyTable(id int IDENTITY(1,1) NOT NULL, Tag nvarchar(200) NOT NULL, StartTime datetime NOT NULL)
DECLARE @day int, @month int, @year int
SELECT @day = 15, @month = 1, @year = 2015
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MyTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MySuperTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
SELECT @day = 16, @month = 1, @year = 2015
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MyTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MySuperTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
SELECT @day = 18, @month = 1, @year = 2015
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MyTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MySuperTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
SELECT @day = 19, @month = 1, @year = 2015
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MyTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MySuperTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
SELECT @day = 26, @month = 1, @year = 2015
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MyTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
INSERT INTO dbo.MyTable(Tag, StartTime) VALUES('MySuperTag',dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1))
再现的步骤(查询):
这不应返回任何值,因为时间跨度中有值。
DECLARE @day int, @month int, @year int
DECLARE @StartTime datetime
DECLARE @EndTime datetime
SELECT @day = 17, @month = 1, @year = 2015
SET @StartTime = dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)
SET @EndTime = dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1 + 3)
SELECT * FROM (SELECT id, Tag, StartTime FROM dbo.MyTable WHERE StartTime < @StartTime AND Tag NOT IN ( SELECT Tag FROM dbo.MyTable WHERE (StartTime > @StartTime AND StartTime < @EndTime))) as d WHERE EXISTS ( SELECT Tag, StartTime, ROW_NUMBER FROM ( SELECT Tag, StartTime, ROW_NUMBER() OVER(PARTITION BY Tag ORDER BY StartTime DESC) AS ROW_NUMBER FROM dbo.MyTable WHERE StartTime < @StartTime) AS b WHERE ROW_NUMBER = '1')
再现的步骤(QUERY2):
这应该在时间跨度之前产生最新值,因为在时间跨度中没有值。
SELECT @day = 21, @month = 1, @year = 2015
SET @StartTime = dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)
SET @EndTime = dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1 + 3)
SELECT * FROM (SELECT id, Tag, StartTime FROM dbo.MyTable WHERE StartTime < @StartTime AND Tag NOT IN ( SELECT Tag FROM dbo.MyTable WHERE (StartTime > @StartTime AND StartTime < @EndTime))) as d WHERE EXISTS ( SELECT Tag, StartTime, ROW_NUMBER FROM ( SELECT Tag, StartTime, ROW_NUMBER() OVER(PARTITION BY Tag ORDER BY StartTime DESC) AS ROW_NUMBER FROM dbo.MyTable WHERE StartTime < @StartTime) AS b WHERE ROW_NUMBER = '1')
编辑:在预期结果部分添加了“每个标签的最新值”。
答案 0 :(得分:1)
以下是修改后问题的修订答案:
SELECT [A].* FROM [dbo].[MyTable] AS [A]
INNER JOIN (
SELECT [Tag], MAX([StartTime]) AS [StartTime]
FROM [dbo].[MyTable]
WHERE [StartTime] < @StartTime
GROUP BY [Tag]
) AS B ON ([A].[Tag] = [B].[Tag] AND [A].[StartTime] = [B].[StartTime])
WHERE
[A].[StartTime] < @StartTime AND
0 = (
SELECT COUNT(*)
FROM [dbo].[MyTable]
WHERE [StartTime] BETWEEN @StartTime AND @EndTime
)
;
已加入的子查询为@StartTime
之前的每个标记计算最新日期并加入其自身,以便可以返回整行(使用id
)。< / p>
答案 1 :(得分:0)
SELECT *
FROM MyTable t
WHERE StartTime < @start
AND id =
(SELECT TOP 1 mt.id FROM MyTable mt WHERE mt.Tag = t.Tag ORDER BY StartTime DESC)
AND NOT EXISTS
(SELECT 1 FROM MyTable WHERE StartTime >= @start AND StartTime <= @end)
ORDER BY StartTime DESC;
答案 2 :(得分:0)
以下内容应大致为您所寻找:
SELECT TOP 1 *
FROM [dbo].[MyTable]
WHERE
[StartTime] < @StartTime AND
0 = (
SELECT COUNT(*)
FROM [dbo].[MyTable]
WHERE [StartTime] BETWEEN @StartTime AND @EndTime
)
ORDER BY [StartTime] DESC;
当0 = (SELECT COUNT(*) ...)
和@StartTime
之间存在数据时,@EndTime
位会导致查询不返回任何数据。然后,查询的其余部分只是选择@StartTime
之前的第一行。
0 = (SELECT COUNT(*) ...)
与EXISTS(SELECT 1 ...)
的查询计划比较