简体   繁体   English

显示 3 个或更多连续行(Sql)

[英]display 3 or more consecutive rows(Sql)

I have a table with below data我有一张包含以下数据的表格

+------+------------+-----------+
| id   | date1      | people    |
+------+------------+-----------+
| 1    | 2017-01-01 | 10        |
| 2    | 2017-01-02 | 109       |
| 3    | 2017-01-03 | 150       |
| 4    | 2017-01-04 | 99        |
| 5    | 2017-01-05 | 145       |
| 6    | 2017-01-06 | 1455      |
| 7    | 2017-01-07 | 199       |
| 8    | 2017-01-08 | 188       |
+------+------------+-----------+

now what i am trying to do is to display 3 consecutive rows where people were >=100 like this现在我要做的是显示 3 个连续的行,其中人们 >=100 像这样

+------+------------+-----------+
| id   | date1      | people    |
+------+------------+-----------+
| 5    | 2017-01-05 | 145       |
| 6    | 2017-01-06 | 1455      |
| 7    | 2017-01-07 | 199       |
| 8    | 2017-01-08 | 188       |
+------+------------+-----------+

can anyone help me how to do this query using oracle database.谁能帮助我如何使用 oracle 数据库进行此查询。 I am able to display rows which are above 100 but not in a consecutive way我能够显示超过 100 行但不是以连续方式显示的行

Table creation(reducing typing time for people who will be helping)表格创建(减少将要提供帮助的人的打字时间)

CREATE TABLE stadium
   ( id int  
   , date1 date, people int 
   );

    Insert into stadium values (    
 1,TO_DATE('2017-01-01','YYYY-MM-DD'),10);

Insert into stadium values       
 (2,TO_DATE('2017-01-02','YYYY-MM-DD'),109);

Insert into stadium values(       
 3,TO_DATE('2017-01-03','YYYY-MM-DD'),150);

Insert into stadium values(       
 4,TO_DATE('2017-01-04','YYYY-MM-DD'),99);

Insert into stadium values(     
 5,TO_DATE('2017-01-05','YYYY-MM-DD'),145);

Insert into stadium values(  
 6,TO_DATE('2017-01-06','YYYY-MM-DD'),1455);

Insert into stadium values
(7,TO_DATE('2017-01-07','YYYY-MM-DD'),199);

Insert into stadium values(
 8,TO_DATE('2017-01-08','YYYY-MM-DD'),188);

Thanks in advance for the help在此先感谢您的帮助

Assuming you mean >= 100, there are a couple of ways.假设您的意思是 >= 100,有几种方法。 One method just uses lead() and lag() .一种方法只使用lead()lag() But a simple method defines each group >= 100 by the number of values < 100 before it.但是一个简单的方法将每个组定义为 >= 100,其前面的值的数量 < 100。 Then it uses count(*) to find the size of the consecutive values:然后它使用count(*)来查找连续值的大小:

select s.*
from (select s.*, count(*) over (partition by grp) as num100pl
      from (select s.*,
                   sum(case when people < 100 then 1 else 0 end) over (order by date) as grp
            from stadium s
           ) s
     ) s
where num100pl >= 3;

Here is a SQL Fiddle showing that the syntax works.是一个显示语法有效的 SQL Fiddle。

I'm assuming that both the id and date columns are sequential and correspond to each other (there will need to be additional ROW_NUMBER() if the id s are not sequential with the dates, and more complex logic included if the dates are not necessarily sequential).我假设iddate列都是连续的并且彼此对应(如果id与日期不连续,则需要额外的ROW_NUMBER() ,如果日期不一定包含更复杂的逻辑顺序)。

SELECT 
    *

FROM 
    (
        SELECT
            *
            ,COUNT(date) OVER (PARTITION BY sequential_group_num) AS num_days_in_sequence

        FROM 
            (
                SELECT
                    *
                    ,(id - ROW_NUMBER() OVER (ORDER BY date)) AS sequential_group_num

                FROM
                    stadium

                WHERE 
                    people >= 100

            ) AS subquery1

    ) AS subquery2

WHERE 
    num_days_in_sequence >= 3

That produces the following output:这会产生以下输出:

id          date       people      sequential_group_num num_days_in_sequence
----------- ---------- ----------- -------------------- --------------------
5           2017-01-05 145         2                    4
6           2017-01-06 1455        2                    4
7           2017-01-07 199         2                    4
8           2017-01-08 188         2                    4

By using joins we can display the consecutive rows like this通过使用连接,我们可以像这样显示连续的行

SELECT id, date1, people FROM stadium a WHERE people >= 100
    AND (SELECT people FROM stadium b WHERE b.id = a.id + 1) >= 100
    AND (SELECT people FROM stadium c WHERE c.id = a.id + 2) >= 100 
    OR people >= 100
            AND (SELECT people FROM stadium e WHERE e.id = a.id - 1) >= 100
            AND (SELECT people FROM stadium f WHERE f.id = a.id + 1) >= 100
    OR people >= 100
            AND (SELECT people FROM stadium g WHERE g.id = a.id - 1) >= 100
        AND (SELECT people FROM stadium h WHERE h.id = a.id - 2) >= 100
order by id;
select distinct
   t1.* 
from
   stadium t1 
   join
      stadium t2 
   join
      stadium t3 
where
   t1.people >= 100 
   and t2.people >= 100 
   and t3.people >= 100 
   and 
   ( 
(t1.id + 1 = t2.id 
      and t2.id + 1 = t3.id) 
      or 
      (
         t2.id + 1 = t1.id 
         and t1.id + 1 = t3.id
      )
      or 
      (
         t2.id + 1 = t3.id 
         and t3.id + 1 = t1.id
      )
   )
order by
   id;

SQL script: SQL脚本:

SELECT DISTINCT SS.*
FROM STADIUM SS
INNER JOIN 
(SELECT S1.ID
    FROM STADIUM S1
    WHERE 3 = (
    SELECT COUNT(1)
    FROM STADIUM S2
    WHERE (S2.ID=S1.ID OR S2.ID=S1.ID+1 OR S2.ID=S1.ID+2)
    AND S2.PEOPLE >= 100
    )) AS SS2
    ON SS.ID>=SS2.ID AND SS.ID<SS2.ID+3

select * from( select * , count(*) over (partition by grp) as total from select * from( select * , count(*) over (partition by grp) as total from
(select * , Sum(case when people < 100 then 1 else 0 end) over (order by date) as grp from stadium) T -- inner Query 1 where people >=100 )S--inner query 2 where total >=3 --outer query (选择 * ,总和(当人 < 100 然后 1 否则 0 结束的情况)超过(按日期排序)作为来自体育场的 grp)T - 内部查询 1,其中人员 >=100 )S-- 内部查询 2,其中总计 >= 3 --外部查询

在此处输入图像描述

You can use the following sql script to get the desired output.您可以使用以下 sql 脚本来获得所需的输出。

WITH partitioned AS (
      SELECT *, id - ROW_NUMBER() OVER (ORDER BY id) AS grp
      FROM stadium
      WHERE people >= 100
    ),
    counted AS (
      SELECT *, COUNT(*) OVER (PARTITION BY grp) AS cnt
      FROM partitioned
    )
    
   
    select id , visit_date,people
    from counted
    where cnt>=3

I wrote the following solution for this similar leetcode problem :我为这个类似的 leetcode问题编写了以下解决方案:

with groupVisitsOver100 as (
    select *,
    sum(
        case
            when people < 100 then 1 
        else 0 
        end
       ) over (order by date1) as visitGroups
    from stadium
),
filterUnder100 as (
    select 
        * 
    from groupVisitsOver100
    where people >= 100
),
countGroupsSize as (
    select 
        *,
        count(*) over (partition by visitGroups) as groupsSize
    from filterUnder100
)

select id, date1, people from countGroupsSize where groupsSize >= 3 order by date1

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM