SQL 2008中的LAG()函数

时间:2019-07-17 07:07:51

标签: sql sql-server sql-server-2008

我已经查看了有关此问题的其他一些问题,我们正在尝试使包含LAG()函数的存储过程正常工作,但是我们现在尝试在其上安装实例的机器是SQL 2008,我们可以不使用

SELECT se.SetID,SetName,ParentSetId,      
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,      
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable,      
Case when (LAG(se.ParentSetId) OVER(ORDER BY se.ParentSetId) <> ParentSetId) then 2 else 1 end level , 
QuestionType   
FROM  tblSet se      
LEFT join tblQuestion qu on qu.SetID=se.SetID        
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1      
where CollectionId=@colID and se.IsDeleted=0       
order by  se.SetID        

到目前为止,我尝试过的操作(编辑以反映Zohar Peled的建议)

SELECT se.SetID,se.SetName,se.ParentSetId,      
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,      
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable, 
(case when row_number() over (partition by se.parentsetid
                              order by se.parentsetid
                             ) = 1
      then 1 else 2
 end) as level,
QuestionType 
FROM  tblSet se
left join tblSet se2 on se.ParentSetId = se2.ParentSetId -1
LEFT join tblQuestion qu on qu.SetID=se.SetID
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1      
where se.CollectionId=@colID and se.IsDeleted=0       
order by  se.SetID      

当我并排运行它们时,似乎并没有带出所有相同的记录,并且级别值似乎也不同

我已将某些输出从包含LAG()的版本中放入HTML格式的表格中(第一个结果),然后第二个是新版本,其中的级别不同。

https://jsfiddle.net/gyn8Lv3u/

2 个答案:

答案 0 :(得分:1)

LAG()可以使用Jeroen在评论中写道的自连接来实现,也可以使用相关子查询来实现。在这种情况下,它是一个简单的lag(),因此相关子查询也很简单:

SELECT se.SetID,SetName,ParentSetId,      
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,      
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable,      
Case when (
    (
        SELECT TOP 1 ParentSetId
        FROM tblSet seInner
        WHERE seInner.ParentSetId < se.ParentSetId
        ORDER BY seInner.ParentSetId DESC
    )    
    <> ParentSetId) then 2 else 1 end level , 
QuestionType   
FROM  tblSet se      
LEFT join tblQuestion qu on qu.SetID=se.SetID        
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1      
where CollectionId=@colID and se.IsDeleted=0       
order by  se.SetID    

如果您指定了偏移量,则使用关联的子查询很难实现,而自联接将使解决方案变得容易得多。

答案 1 :(得分:0)

样本数据和所需结果会有所帮助。这个构造:

(case when (LAG(se.ParentSetId) OVER(ORDER BY se.ParentSetId) <> ParentSetId) then 2 else 1
 end) as level 

很奇怪。您落后于order by中使用的唯一列。那讲得通。但是随后您将值与同一列进行比较,这意味着存在重复项。

如果重复,则order by se.ParentSetId不稳定。也就是说,由于对重复值进行了排序,因此“上一个”行是不确定的。您可以运行两次查询并获得不同的结果。

我猜您想为每个父集ID分配一行值1。如果是这样,则在任何一个数据库中,您都可以使用:

(case when row_number() over (partition by se.parentsetid
                              order by se.parentsetid
                             ) = 1
      then 1 else 2
 end) as level

这也存在顺序不稳定的问题。您可以通过将order by更改为您真正想要的内容来解决此问题。