【问题标题】:Selecting distinct timestamps from an ORACLE database从 ORACLE 数据库中选择不同的时间戳
【发布时间】:2021-08-02 15:45:00
【问题描述】:

我试图限制我在 python 中处理/分析之前提取的数据量。 主要是由于内存限制。

每笔交易都会产生大约 3-4 个不同的交易事件。

-----------
trx_id     timestamp
trx_1    | 2021.01.01 15:45:40
trx_1_2  | 2021.01.01 15:45:40
trx_1_3  | 2021.01.01 15:45:40
trx_2    | 2021.02.01 14:15:40
trx_2_2  | 2021.02.01 14:15:40
trx_2_3  | 2021.02.01 14:15:40

我只需要每个时间戳 1 条记录。

-----------
trx_id   timestamp
trx_1  | 2021.01.01 15:45:40
trx_2  | 2021.02.01 14:15:40

我已经尝试过以下建议:

On the ORACLE community forum

select distinct(date) return the same date several time

我也尝试过各种变体

SELECT DISTINCT TRUNC(timestamp, 'DD')
SELECT DISTINCT TRUNC(timestamp)
SELECT DISTINCT to_char(timestamp, 'yyyy-mm-dd')

但是没有结果。

【问题讨论】:

  • 而不是链接到没有帮助的东西,我宁愿看到一些示例数据,说明你拥有什么以及你想用它做什么。您发布的 SELECT 不会“限制”任何内容,因此我很难理解这个问题。
  • @Littlefoot 我添加了一些示例数据和预期结果。
  • 如果有三个 trx_id 值具有相同的时间戳(假设它们相同 - 您没有显示小数秒),您将如何决定显示哪一个?
  • 你指的timestamp是实际的timestamp,还是date

标签: sql oracle greatest-n-per-group


【解决方案1】:

您可以使用ROW_NUMBER解析函数,并通过TRX_ID的前5个字符和时间戳进行分区:

SELECT trx_id, ts
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER (
           PARTITION BY SUBSTR( trx_id, 1, 5 ), ts ORDER BY trx_id
         ) AS rn
  FROM   table_name t
)
WHERE  rn = 1;

对于您的示例数据:

CREATE TABLE table_name ( trx_id, ts ) AS
SELECT 'trx_1',   TIMESTAMP '2021-01-01 15:45:40' FROM DUAL UNION ALL
SELECT 'trx_1_2', TIMESTAMP '2021-01-01 15:45:40' FROM DUAL UNION ALL
SELECT 'trx_1_3', TIMESTAMP '2021-01-01 15:45:40' FROM DUAL UNION ALL
SELECT 'trx_2',   TIMESTAMP '2021-02-01 14:15:40' FROM DUAL UNION ALL
SELECT 'trx_2_2', TIMESTAMP '2021-02-01 14:15:40' FROM DUAL UNION ALL
SELECT 'trx_2_3', TIMESTAMP '2021-02-01 14:15:40' FROM DUAL;

输出:

TRX_ID TS
trx_1 2021-01-01 15:45:40.000000000
trx_2 2021-02-01 14:15:40.000000000

如果您可以拥有其他具有不同长度模式的TRX_ID,那么您可以查找第二个下划线字符并获取其之前的子字符串:

SELECT trx_id, ts
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER (
           PARTITION BY CASE INSTR( trx_id, '_', 1, 2 )
                        WHEN 0
                        THEN trx_id
                        ELSE SUBSTR( trx_id, 1, INSTR( trx_id, '_', 1, 2 ) - 1 )
                        END,
                        ts
           ORDER     BY trx_id
         ) AS rn
  FROM   table_name t
)
WHERE  rn = 1;

db小提琴here

【讨论】:

  • 我只能访问表视图而不是实际表,而且我很确定我不能对视图进行分区?
  • @little_adventurer 你没有改变桌面或视图上的任何东西;分析函数可以在整个行集的一个窗口上工作,也可以在分区子句定义的多个子窗口上工作,但这是函数内部的,不会更改基础数据。你为什么不试试这个查询,看看它是否能解决你的问题?
  • 此解决方案也不起作用。我发布的 trx_id 结构是任意的。实际上,它们是相同时间戳的随机(ish)数字序列,增量为 1。我发布了 trx_1, trx_1_2 作为一个例子,在同一事务中使用(看似)相同的时间戳
  • @little_adventurer 然后edit 您的问题并给出适当的minimal reproducible example,包括更多代表性 数据示例和更新数据的适当预期输出。当您提供一些示例数据然后说您的示例数据不完全合适但不告诉我们什么是合适的时,我不知道您希望我们如何猜测您的问题的解决方案。
【解决方案2】:

你可以使用聚合:

select min(trx_id), timestamp
from t
group by timestamp;

Here 是一个 dbfiddle。

【讨论】:

  • 如果有两个trx_id具有相同的时间戳会发生什么? db<>fiddle
  • @MT0 。 . .你需要问OP。问题很明确:“我只需要每个时间戳 1 条记录。”。
猜你喜欢
  • 2010-12-14
  • 1970-01-01
  • 2017-05-26
  • 2016-10-21
  • 1970-01-01
  • 2020-01-17
  • 2021-02-23
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多