sql:获取连续组' n'行(可能在中间)

时间:2015-12-17 09:31:32

标签: sql postgresql-9.3 gaps-and-islands

下面是我的剧院表:

create table theater
(
   srno integer, 
   seatno integer, 
   available boolean
);

insert into theater
values
(1, 100,true),
(2, 200,true),
(3, 300,true),
(4, 400,false),
(5, 500,true),
(6, 600,true),
(7, 700,true),
(8, 800,true);

我想要一个sql,它应该输入' n'并给我第一个' n'连续可用的席位,如

  • 如果n = 2,则输出应为100,200
  • 如果n = 4,则输出应为500,600,700,800

注意:我正在尝试为postgres 9.3构建查询

4 个答案:

答案 0 :(得分:3)

SQL-Server 中,您可以执行以下操作:

DECLARE @num INT = 4

;WITH cte AS
(
SELECT *,COUNT(1) OVER(PARTITION BY cnt) pt  FROM
(
    SELECT tt.*
        ,(SELECT COUNT(srno) FROM theater t WHERE available <> 'true' and srno < tt.srno) AS cnt
    FROM  theater tt
    WHERE available = 'true'
) t1
)
SELECT TOP (SELECT @num) srno, seatno, available
FROM cte
WHERE pt >= @num

<强>输出

srno    seatno  available
5       500 true
6       600 true
7       700 true
8       800 true

答案 1 :(得分:2)

这将找到可用的座位。为sqlserver 2008 +编写:

DECLARE @num INT = 4

;WITH CTE as
(
  SELECT 
    srno-row_number() over (partition by available order by srno) grp, 
    srno, seatno, available
  FROM theater
), CTE2 as
(
  SELECT grp, count(*) over (partition by grp) cnt,
    srno, seatno, available 
  FROM CTE
    WHERE available = 'true'

)
SELECT top(@num)
  srno, seatno, available
FROM CTE2
WHERE cnt >= @num
ORDER BY srno

结果:

srno  seatno  available
5     500     1
6     600     1
7     700     1
8     800     1

答案 2 :(得分:0)

        -- naive solution without window using functions
        -- [the funny +-100 constants are caused by
        -- "consecutive" seats being 100 apart]
        -- -------------------------------------------
WITH    bot AS ( -- start of an island --
        SELECT seatno FROM theater t
        WHERE  t.available
        AND NOT EXISTS (select * from theater x
                where x.available AND x.seatno = t.seatno -100)
        )
,       top AS ( -- end of an island --
        SELECT seatno FROM theater t
        WHERE t.available
        AND NOT EXISTS (select * from theater x
                where x.available AND x.seatno = t.seatno +100)
        )
,       mid AS ( -- [start,end] without intervening gaps --
        SELECT l.seatno AS bot, h.seatno AS top
        FROM bot l
        JOIN top h ON h.seatno >= l.seatno
                AND NOT EXISTS (
                SELECT * FROM theater x
                WHERE NOT x.available
                AND x.seatno >= l.seatno AND x.seatno <= h.seatno)
        )
        -- all the consecutive ranges
        -- [ the end query should select from this
        -- , using "cnt >= xxx" ]
SELECT bot, top
        , 1+(top-bot)/100 AS cnt
FROM mid;

结果:

 bot | top | cnt 
-----+-----+-----
 100 | 300 |   3
 500 | 800 |   4
(2 rows)

答案 3 :(得分:-2)

谢谢你们,但我已经完成了如下所示,

select srno, seatno from (
select *, count(0) over (order by grp) grp1 from (
  select t1.*,  
          sum(group_flag) over (order by srno) as grp
  from (
      select *,
             case
                when lag(available) over (order by srno) = available then null
                else 1
              end as group_flag
      from theater
  ) t1 ) tx ) tr where tr.available=true and tr.grp1 >= 2 limit 2