SQL Server 2008 R2:使用多个CTE获取日期记录

SQL Server 2008 R2:使用多个CTE获取日期记录,sql,sql-server,tsql,sql-server-2008-r2,Sql,Sql Server,Tsql,Sql Server 2008 R2,我有下表: 表:TBallocation 注意:我想找到每个日期的第一个、中间和最后一个位置 预期产出: 输出解释: FirstLocation-这应基于日期和时间的订单,并且将是该日期的第一次 中间位置-这不应等于FirstLocation和LastLocation,但它是 出现在计数较多的位置之间或任何平局场景中。 如果两行之间没有任何值,则为空,如第3行所示 LastLocation-这应基于按日期和时间排序的订单,并且将是该日期的最后时间 我的尝试: 我将使用关联子查询和应用运算符: s

我有下表:

表:TBallocation

注意:我想找到每个日期的第一个、中间和最后一个位置

预期产出:

输出解释:

FirstLocation-这应基于日期和时间的订单,并且将是该日期的第一次

中间位置-这不应等于FirstLocation和LastLocation,但它是 出现在计数较多的位置之间或任何平局场景中。 如果两行之间没有任何值,则为空,如第3行所示

LastLocation-这应基于按日期和时间排序的订单,并且将是该日期的最后时间

我的尝试:

我将使用关联子查询和应用运算符:

select distinct t.coldate, t1.*, 
       ( select top 1 ColValue
         from TblLocation
         where (coldate = t.coldate and 
                ColValue <> t1.FirstLocation and ColValue <> t2.LastLocation)
         order by count(*) over() desc
       ) as MidName, t2.*
from TblLocation t cross apply 
     (select top 1 ColValue as FirstLocation 
      from TblLocation
      where coldate = t.coldate
      order by coltime
     ) t1 cross apply 
     (select top 1 ColValue as LastLocation
      from TblLocation
      where coldate = t.coldate
      order by coltime desc
     ) t2;
接近

declare @t TABLE (ColDate DATE, ColTime time, Colvalue VARCHAR(50));
INSERT INTO @t VALUES
('2018-01-01','01:10:11','Location1'),
('2018-01-01','02:10:11','Location2'),
('2018-01-01','03:10:11','Location3'),
('2018-01-01','11:10:11','Location4'),

('2018-01-02','01:10:11','Location1'),
('2018-01-02','02:10:11','Location2'),
('2018-01-02','03:10:11','Location2'),
('2018-01-02','01:10:11','Location3'),
('2018-01-02','03:15:11','Location4'),

('2018-01-03','02:10:11','Location1'),
('2018-01-03','02:50:11','Location1'),
('2018-01-03','03:10:11','Location1');

--select * from @t order by ColDate, ColTime

with cte as 
( select * 
       , row_number() over (partition by ColDate order by ColTime asc)  as tasc
       , row_number() over (partition by ColDate order by ColTime desc) as tdsc
  from @t 
) 

select distinct
       cteMin.ColDate, cteMin.ColTime
     , cteMin.Colvalue as [cteMin.Colvalue]
     , cteMid.Colvalue as [cteMid.Colvalue]
     , cteMax.Colvalue as [cteMax.Colvalue]
from cte cteMin 
join cte cteMax
  on cteMin.ColDate = cteMax.ColDate 
 and cteMin.tasc = 1 
 and cteMax.tdsc = 1
left join cte cteMid 
  on cteMid.ColDate = cteMin.ColDate 
 and cteMid.tasc > 1
 and cteMid.tdsc = 2
 and cteMid.Colvalue <> cteMin.Colvalue 
 and cteMid.Colvalue <> cteMax.Colvalue
WITH CTEMain AS
(
    SELECT ColDate,ColTime, ColValue, ROW_NUMBER() OVER(PARTITION BY ColDate ORDER BY ColDate,ColTime ASC) Rn 
    FROM dbo.TblLocation
),
CTEMinMax AS
(
    SELECT MIN(Rn) AS MinRn,MAX(Rn) AS MaxRn
    FROM CTEMain
),
CX AS 
(
    SELECT c1.ColDate,c1.Colvalue AS FirstLocation,
       c2.Colvalue AS LastLocation
    FROM CTEMain c1 
    INNER JOIN CTEMinMax cmin ON c1.Rn = cmin.MinRn
    INNER JOIN CTEMain c2 ON 1 = 1
    INNER JOIN CTEMinMax cmax ON c2.Rn = cmax.MaxRn
), 
CXX AS
( 
    SELECT TOP 1 ROW_NUMBER() OVER(PARTITION BY Colvalue ORDER BY Rn DESC) Rnk,ColValue,Rn
    FROM CTEMain c1
    INNER JOIN CX x ON c1.colvalue <> x.FirstLocation AND c1.colvalue <> x.LastLocation
    GROUP BY ColValue,Rn
    ORDER BY Rnk DESC
)
SELECT ColDate,CX.FirstLocation,(SELECT ColValue FROM CXX) AS MidName, cx.LastLocation
FROM CX
ColDate     FirstLocation   MidName     LastLocation
-----------------------------------------------------
2018-01-01  Location1       Location2   Location4
2018-01-02  Location1       Location2   Location4
2018-01-03  Location1       Location2   Location4
select distinct t.coldate, t1.*, 
       ( select top 1 ColValue
         from TblLocation
         where (coldate = t.coldate and 
                ColValue <> t1.FirstLocation and ColValue <> t2.LastLocation)
         order by count(*) over() desc
       ) as MidName, t2.*
from TblLocation t cross apply 
     (select top 1 ColValue as FirstLocation 
      from TblLocation
      where coldate = t.coldate
      order by coltime
     ) t1 cross apply 
     (select top 1 ColValue as LastLocation
      from TblLocation
      where coldate = t.coldate
      order by coltime desc
     ) t2;
declare @t TABLE (ColDate DATE, ColTime time, Colvalue VARCHAR(50));
INSERT INTO @t VALUES
('2018-01-01','01:10:11','Location1'),
('2018-01-01','02:10:11','Location2'),
('2018-01-01','03:10:11','Location3'),
('2018-01-01','11:10:11','Location4'),

('2018-01-02','01:10:11','Location1'),
('2018-01-02','02:10:11','Location2'),
('2018-01-02','03:10:11','Location2'),
('2018-01-02','01:10:11','Location3'),
('2018-01-02','03:15:11','Location4'),

('2018-01-03','02:10:11','Location1'),
('2018-01-03','02:50:11','Location1'),
('2018-01-03','03:10:11','Location1');

--select * from @t order by ColDate, ColTime

with cte as 
( select * 
       , row_number() over (partition by ColDate order by ColTime asc)  as tasc
       , row_number() over (partition by ColDate order by ColTime desc) as tdsc
  from @t 
) 

select distinct
       cteMin.ColDate, cteMin.ColTime
     , cteMin.Colvalue as [cteMin.Colvalue]
     , cteMid.Colvalue as [cteMid.Colvalue]
     , cteMax.Colvalue as [cteMax.Colvalue]
from cte cteMin 
join cte cteMax
  on cteMin.ColDate = cteMax.ColDate 
 and cteMin.tasc = 1 
 and cteMax.tdsc = 1
left join cte cteMid 
  on cteMid.ColDate = cteMin.ColDate 
 and cteMid.tasc > 1
 and cteMid.tdsc = 2
 and cteMid.Colvalue <> cteMin.Colvalue 
 and cteMid.Colvalue <> cteMax.Colvalue