简体   繁体   English

Oracle - SQL 查询根据列值将数据从一个表分装到另一个表?

[英]Oracle - SQL query to bin the data from one table to another based on a column value?

What SQL query to use to generate Table2 from Table1 (tables shown below)?什么 SQL 查询用于从Table1生成Table2 (表如下所示)?

Table2 needs to bin the timestamps from Table1 into start and end times according to the Table1.Status field. Table2需要根据Table1.Status字段将Table1中的时间戳分为开始和结束时间。 As a result Table2.Status should toggle between 0 and 1 in every row.结果Table2.Status应该在每一行中在 0 和 1 之间切换。

Table2.StartTime = 1st value of Table1.TimeStamp whenever Table1.Status changes from 1 to 0 or viceversa. Table2.StartTime = Table1.Status Table1.TimeStamp 1 变为 0 或反之亦然。

Table2.EndTime = (1st value of Table1.TimeStamp of Table1.Status next change) - 1millisecond Table2.EndTime = ( Table1.TimeStamp of Table1.Status next change 的第一个值) - 1 毫秒

The first record in Table1 can start from any Status - 1 or 0. Table1中的第一条记录可以从任何Status - 1 或 0 开始。

Table1

TimeStamp                               Status
11-NOV-11 12.45.45.445000000 AM           1
11-NOV-11 12.46.45.445000000 AM           1
11-NOV-11 12.47.45.445000000 AM           1
11-NOV-11 12.48.45.445000000 AM           0
11-NOV-11 12.49.45.445000000 AM           0
11-NOV-11 12.50.45.445000000 AM           1
11-NOV-11 12.51.45.445000000 AM           0
11-NOV-11 12.52.45.445000000 AM           0
11-NOV-11 12.53.45.445000000 AM           1
...
Table2

StartTime                                        EndTime                     Status
11-NOV-11 12.45.45.445000000 AM      11-NOV-11 12.48.45.444000000 AM            1
11-NOV-11 12.48.45.445000000 AM      11-NOV-11 12.50.45.444000000 AM            0
11-NOV-11 12.50.45.445000000 AM      11-NOV-11 12.51.45.444000000 AM            1
11-NOV-11 12.51.45.445000000 AM      11-NOV-11 12.53.45.444000000 AM            0
...

Any help would be appreciated.任何帮助,将不胜感激。

select min(t2.TimeStamp) Start_time
  , lead(min(t2.TimeStamp), 1)over(order by min(t2.TimeStamp))  - INTERVAL '0.001' SECOND End_time
  , t2.status
from (
  select t1.TimeStamp TimeStamp, STATUS, group_tag, first_value(group_tag ignore nulls)over(order by t1.TimeStamp ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) group_tag_gap_filling
  from (
      select t.TimeStamp, Status, case when lead(status, 1, 2)over(order by t.TimeStamp) != status then row_number()over(order by t.TimeStamp)end group_tag
      from Table1 t
    )t1
  )t2
group by t2.group_tag_gap_filling, t2.status
;

First, in inline view "t1", I create temporary groups Then Secondly, I fill in the gap for all temporary groups Then I extract what is need using min aggregation function, and lead analytic function, and I extract 0.001 second from end_time首先,在内联视图“t1”中,我创建临时组然后其次,我填补所有临时组的空白然后我使用最小聚合 function 提取需要的内容,并引导分析 function,然后我从 end_time 中提取 0.001 秒

This is a gaps and islands problem, with a slight twist.这是一个差距和孤岛问题,略有不同。 The twist being that you don't want to report the most recent timestamp record for each island, but rather you want to report the record immediately following after that most recent record.不同之处在于,您不想报告每个岛屿的最新时间戳记记录,而是想报告紧随该最新记录之后的记录。 So, we can use the difference in row numbers method, and also compute the lead of the timestamp column.因此,我们可以使用行号差法,也可以计算时间戳列的前导。

WITH cte AS (
    SELECT t.*, ROW_NUMBER() OVER (ORDER BY ts) rn1,
                ROW_NUMBER() OVER (PARTITION BY Status ORDER BY ts) rn2,
                LEAD(ts) OVER (ORDER BY ts) AS ts_lead
    FROM Table1 t
)

SELECT MIN(ts) AS StartTime, MAX(ts_lead) AS EndTime
FROM cte
GROUP BY Status, rn1 - rn2
HAVING MAX(ts_lead) IS NOT NULL
ORDER BY MIN(ts);

从下面的演示链接截屏

Demo 演示

You can achieve it using the analytical functions and GROUP BY as follows:您可以使用analytical函数和GROUP BY实现它,如下所示:

SELECT MIN(TIMESTAMP) AS STARTTIME, MAX(TIMESTAMP) AS ENDTIME, STATUS 
  FROM
       (SELECT T.TIMESTAMP, T.STATUS, SUM(CHANGE_POINT) OVER (ORDER BY TIMESTAMP) AS SM 
          FROM
               (SELECT T.TIMESTAMP, T.STATUS, 
                       CASE WHEN LAG(STATUS) OVER (ORDER BY TIMESTAMP) <> STATUS THEN 1 END AS CHANGE_POINT
                  FROM YOUR_TABLE T
                ) T
        )
GROUP BY SM, STATUS

You can also use the MATCH_RECOGNIZE clause as follows:您还可以使用MATCH_RECOGNIZE子句,如下所示:

SELECT * FROM YOUR_TABLE
MATCH_RECOGNIZE
(
 ORDER BY TIMESTAMP
  MEASURES
    FIRST( TIMESTAMP ) AS STARTDATE,
    LAST( TIMESTAMP ) AS ENDDATE,
    FIRST( STATUS ) AS STATUS
  ONE ROW PER MATCH
  PATTERN( same_field+ )
  DEFINE same_field AS FIRST(STATUS) = STATUS 
);

There are many ways to solve gaps-and-islands problems.有很多方法可以解决间隙和孤岛问题。 In this case, the simplest method is two window functions and filtering:在这种情况下,最简单的方法是两个 window 函数和过滤:

select status, ts as start_time, lead(ts) over (order by ts) as end_time
from (select t1.*, lag(status) over (order by ts) as prev_status
      from table1 t1
     ) t1
where prev_status is null or prev_status <> status
order by start_time;

The logic is simple:逻辑很简单:

  • Keep each row where the status changes, filtering out all other rows.保留状态更改的每一行,过滤掉所有其他行。
  • Use lead() to get the ending timestamp.使用lead()获取结束时间戳。

Here is a db<>fiddle. 是一个 db<>fiddle。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 基于索引值将列从一个表复制到另一个表的 SQL 查询 - SQL query to copy column from one table to another table based off index value SQL查询根据来自另一列的数据更新一列 - SQL Query to Update One Column Based on Data from Another Oracle sql-将一个表中的sql行值作为列值计数添加到另一表中 - Oracle sql - Adding sql row value from one table as column value count to another table sql查询从审计表中获取数据,其中列匹配一个值,但不匹配另一个 - sql query to get data from an audit table where column match one value, but not another Oracle-SQL查询以从另一个表中的列返回值,其中值等于另一个列 - Oracle - SQL Query to return a value from a column in another table where value equals a different column Oracle SQL更新一个表列以及另一表的值 - Oracle SQL Update one table column with the value of another table SQL-基于一个表与另一个表的联接(第一个表的行值到第二个表的列值) - SQL - Joining one table with another based on ( Row value from first table to Column value of second table) 从一个表中选择,插入到另一个表中 oracle sql 查询 - select from one table, insert into another table oracle sql query 选择一个表与另一个表的否定以及oracle主表sql查询中的数据 - Select Negation of one table from another along with data in master table sql query for oracle Oracle SQL:根据另一个表中给定条件的列中的找到值进行插入 - Oracle SQL: Insert based on found value in a column given condition from another table
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM