【问题标题】:SQL: a way to compare rows from result set without self-joinSQL:一种在没有自连接的情况下比较结果集中行的方法
【发布时间】:2013-10-01 19:40:17
【问题描述】:

有没有办法在没有自连接的情况下比较表的 2 行?

我有一个包含以下列的事件表:ID、日期、工具。我查询它,并将行号添加到结果集中(按日期排序,分别针对每个工具)。现在我想知道第 1 行和第 4 行之间的时间差是否超过一周。
我可以通过将我的查询连接到自身来实现这一点(非常简单),但是它会使查询运行两次(对吗?)这不是很有效(因为我的查询并不简单并且已经需要一些连接)。有没有更聪明的方法来实现这一点?

我正在使用 SQL 服务器(不确定哪个版本;可能是 2008 年),并从 ASP.NET 应用程序查询,所以我没有对数据库的管理访问权限,并且一些高级的东西将无法工作(但我我愿意尝试每一个建议并检查)。 谢谢。

【问题讨论】:

  • 您可以使用临时表来存储结果集,然后进行您需要的操作。
  • @dcp1986:我该怎么做?
  • 这取决于您使用的 SQL Server 版本。例如:如果您在 >=2005 SQL Server 上,则 Windowing Functions 将允许您做您想做的事,而无需自我加入。因此,请发布您使用的 SQL Server 版本。
  • @SashikanthDareddy:我不确定,可能是 2008 年,肯定 >=2005。我可以使用什么窗口函数?我不知道有什么合适的。
  • @我很抱歉,看来我认为可能有帮助的窗口功能部分仅在 SQL Server 2012 中可用。请参阅:technet.microsoft.com/en-us/library/ms189461(v=sql.110).aspx。它是在任意编号上定义范围的能力。

标签: sql sql-server self-join


【解决方案1】:

您可以使用窗口函数来实现您的目标,但也许 over(partition by ... order by) 就足够了 (http://www.sqlfiddle.com/#!6/2d448/1):

IF OBJECT_ID('tempdb..#SomeTable', 'U') IS NOT NULL
BEGIN 
    DROP TABLE #SomeTable
END

create table #SomeTable (Id int, [date] datetime, tool nvarchar(80), description nvarchar(80))

DECLARE @date AS DATETIME

SET @date = CAST('2013-01-10' as datetime) 

declare @i as int = 0
declare @j as int = 0
declare @k as int = 0

WHILE (@i < 100)
begin
    set @i = @i + 1
    set @j = 0
    WHILE (@j < 100)
    begin
        set @j = @j + 1
        set @k = CAST(RAND() * 100 as int)      
        insert into #SomeTable (Id, [date], tool, description) values (@i*@j, DATEADD(dd,@k,@date), 'tool-' + STUFF('000', 3-LEN(@i)+1, LEN(@i), @i) , 'description-' + CAST(@i as nvarchar(10)) + '-' + CAST(@j as nvarchar(10)))
    end
end
--may be this will be enough
--select *, DATEDIFF(dd, MIN([date]) OVER(PARTITION BY tool), [date]) AS 'days' from #SomeTable order by tool, days
--sql 2012 only
--4 rows window
--select *, DATEDIFF(dd, MIN([date]) OVER(PARTITION BY tool ORDER BY tool, [date] ROWS BETWEEN 4 PRECEDING AND CURRENT ROW), [date]) AS 'days' from #SomeTable order by tool, days
select *, DATEDIFF(dd, MIN([date]) OVER(ORDER BY tool, [date] ROWS BETWEEN 4 PRECEDING AND CURRENT ROW), [date]) AS 'days' from #SomeTable order by tool, days

【讨论】:

    猜你喜欢
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多