将某些记录滑动到同一日期的运行结束

时间:2015-10-05 13:18:48

标签: sql oracle sorting

我有三列 -

  • TheDate - 显然是约会。
  • TheID - 一个严格增加的ID。
  • TheType - 记录类型。

我想在几乎所有情况下都按TheID排序,除了一种记录类型。特殊记录类型的记录必须出现在具有相同日期的所有记录的末尾。

示例:

Move record type 101 to the end of that date/time run

我希望记录类型101在所有其他具有相同日期的记录后显示。在所有其他情况下TheID控制订单。

我的尝试如下:

ORDER BY 
TheDate, 
CASE WHEN TheType = 101 THEN 1 ELSE 0 END, 
TheID

其中几乎做了我想做的事情,但做得更多 - 即它会按TheDate重新排序,而不是我想要的。

如果数据后面出现相同的日期我并不在意 - 只是当包含类型101的记录序列(按TheID排序)都具有相同的日期时我想要类型{{1最后一次。

3 个答案:

答案 0 :(得分:1)

这很复杂。首先,您必须找到连续的日期记录,所以使用

thedate     theid  thetype
2014-07-12   5001       59
2014-07-12   5002      101
2014-07-12   5003       88
2014-07-13   5004       10
2014-07-12   5005       60

您会将2014-07-12标识为前三个记录的一次出现,另一次记录为最后一次记录。第二条记录必须在结果中排​​名第3,而不是#5。

通过使用第一个LAG查看上一条记录来为连续记录提供组密钥,从而在组更改时创建一个标志,然后累积这些标记,从而实现此目的。

select thedate, theid, thetype
from
(
  select 
    thedate, theid, thetype,
    sum(new_group) over (order by theid) as group_key
  from
  (
    select
      thedate, theid, thetype,
      case when lag(thedate) over (order by theid) = thedate then 0 else 1 as new_group
    from mytable
  ) marked
) grouped
order by 
  group_key,
  case when thetype = 101 then 1 else 0 end,
  theid;

答案 1 :(得分:0)

在评论中授予的自由假设TheDate不随递增TheId而递减,如果r1.TheId < r2.TheId则必须是r1.TheDate <= r2.TheDate(&# 39; s非减少的定义)。在这种情况下,首先按TheDate然后按TheId排序会产生与单独排序TheId相同的顺序。从另一个方向看,按TheId排序会自动生成按TheDate聚类的结果,并按日期排序。

但是你已经做的事情与按(TheDateTheId)排序(我们已经建立的只与TheId的排序相同)只是通过移动而不同特殊记录到每个日期集群的末尾,这正是你想要的。因此,您必须按照所需的顺序获得结果;如果你确实有任何问题,那么你必须对你这样做的方式不满意。例如,您可能关心查询性能。

但是,如果您现有的订购确实产生了正确的结果,那么我很难找到一种我希望能提供更好性能的替代方案。毫无疑问,排序可以通过不依赖于TheDate不减少的方式产生,但我希望所有这些都是相对昂贵的计算。

答案 2 :(得分:0)

如果TheID不能为null,那么只需将TheID更改为null作为订单的一部分,其中TheType是一个特殊值:

order by TheDate, 
         case TheType
           when 101 then null
           else TheID
         end nulls last