【问题标题】:Selecting 1 row per day closest to 4am? [duplicate]每天选择最接近凌晨 4 点的 1 行? [复制]
【发布时间】:2016-06-16 22:48:36
【问题描述】:

我们目前正在对返回一系列数据的报告进行查询。客户已指定他们希望总共接收 5 行数据,其中包含前 5 天的数据(由开始日期和结束日期变量定义)。对于每一天,他们都需要最接近凌晨 4 点的行中的数据。

我设法让它工作了一天,但我当然不想仅仅为了获取这些值而合并 5 个单独的选择语句。有什么方法可以通过 CTE 实现这一点?

select top 1 
    'W' as [RecordType]
,   [WellIdentifier]                    as [ProductionPtID]
,   t.Name                              as [Device Name]
,   t.RecordDate --convert(varchar, t.RecordDate, 112) as [RecordDate]
,   TubingPressure                      as [Tubing Pressure]
,   CasingPressure                      as [Casing Pressure]
from #tTempData t
Where cast (t.recorddate as time) = '04:00:00.000'
or datediff (hh,'04:00:00.000',cast (t.recorddate as time)) < -1.2
order by Name, RecordDate desc 

【问题讨论】:

  • @TabAlleman 。 . .我不认为重复会帮助 OP 回答这个问题。
  • 为什么不呢?它显示了获得每组前 1 行的技术。 OP希望每天按时间排列前1行(有你的组/分区),过滤器在凌晨4点之后。我知道如果我是他,这会对我有所帮助。

标签: sql sql-server common-table-expression


【解决方案1】:

假设 #tTempData 仅包含前 5 天的记录

SELECT *
FROM
(
    SELECT *, rn = row_number() over 
                   ( 
                      partition by convert(date, recorddate)
                      order by ABS ( datediff(minute, convert(time, recorddate) , '04:00' )
                   )
    FROM   #tTempData

)
WHERE rn = 1

【讨论】:

  • CTE 对我来说就像魔法一样。但是这两种解决方案都很棒,感谢您的帮助。
  • @Jdsfighter 很好,因为那不是一个。那是一个子查询。
  • 是的。不是 CTE。但在这种情况下,您也可以使用 CTE 来获得您想要的结果 :)。
【解决方案2】:

您可以像这样使用 row_number() 来获取最接近 04:00 的前 5 天

SELECT TOP 5 * FROM (
    select t.* , 
           ROW_NUMBER() OVER(PARTITION BY t.recorddate
                        ORDER BY abs(datediff (minute,'04:00:00.000',cast (t.recorddate as time))) rnk
    from #tTempData t)
WHERE rnk = 1
ORDER BY recorddate DESC

【讨论】:

  • @downvoter 需要解释一下吗?
【解决方案3】:

您可以为此使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by cast(t.recorddate as date)
                                order by abs(datediff(ms, '04:00:00.000',
                                                      cast(t.recorddate as time)
                                                     ))
                               ) seqnum
      from #tTempData t
     ) t
where seqnum = 1;

您可以在子查询中添加适当的where 子句来获取您感兴趣的日期。

【讨论】:

  • 投反对票有什么原因吗?
  • 重复问题中提供的答案不可信?
  • 这主要是因为..其余的答案看起来像是@squirrel提供的答案的欺骗......也包括这个
  • @Yossi,它可能不完全重复,但核心逻辑与 Squirrel 建议的相同,因此它仍然有资格作为欺骗。
  • 是的。我们俩几乎在同一时间发帖。一个帖子上一个帖子下另一个帖子是不公平的,因为它是相似的。我会对此投票!
【解决方案4】:

试试这样的:

select 
    'W' as [RecordType]
,   [WellIdentifier]                    as [ProductionPtID]
,   t.Name                              as [Device Name]
,   t.RecordDate --convert(varchar, t.RecordDate, 112) as [RecordDate]
,   TubingPressure                      as [Tubing Pressure]
,   CasingPressure                      as [Casing Pressure]
from #tTempData t
Where exists
(select 1 from #tTempData t1 where
    ABS(datediff (hh,'04:00:00.000',cast (t.recorddate as time))) < 
    ABS(datediff (hh,'04:00:00.000',cast (t1.recorddate as time)))
    and GETDATE(t.RecordDate) = GETDATE(t1.RecordDate)
)dt
and t.RecordDate between YOURDATERANGE
order by Name, RecordDate desc;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 2011-10-26
    • 2013-01-20
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多