2015-12-17 1 views
3

Ниже мой театр стол:SQL: получить последовательную группу «N» строк (может быть между ними)

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» последовательные доступные места, такие как

  • , если п = 2 вывод должны быть 100,200
  • , если п = 4 вывода должен быть 500.600.700.800

ПРИМЕЧАНИЕ: Я пытаюсь построить запрос для Postgres 9.3

+0

Нам может понадобиться дополнительная информация, чтобы понять вопрос. – Chennakrishna

+0

Какие СУБД вы используете? –

+1

Вы действительно делаете это, используя 3 разных продукта dbms?!? – jarlh

ответ

-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
+0

Странный комментарий, я думаю, вам стоит ответить, если это помогло вам. Вы ответили на свой вопрос и попросили увольнения ... –

+0

lolz, пожалуйста, извините меня, я попросил перестраховать только в том случае, если это вам тоже помогло :) , пожалуйста, не принимайте это, как будто у меня были и ответили на этот вопрос, поскольку длинный. если все настаивают, я могу удалить свой комментарий, чтобы повысить его. – BaajiRao

+0

Я не понимаю, почему это сокращается. Кажется, вернет правильный результат. –

3

В SQL-сервера вы можете сделать это в следующем:

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 
+0

Я установил num в «2», и результата не было ... – Shnugo

+0

Кажется, что нужно работать сейчас ... с моей стороны и надеюсь, что OP действительно нужен SQL Server :-) – Shnugo

+0

Я бы посоветовал вам удалить " # ", поскольку OP будет работать против его физического стола. – Shnugo

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 
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)