如何选择相邻的座位?座位表

时间:2009-12-28 21:24:02

标签: c# sql-server

启者

我有一个票务系统。现在,当用户要求2张或3张票时,我必须选择相邻的地方。 每张票都有一个行号和列号。相邻位置的概念与相邻列号位于同一行。 这些票证位于sql server数据库中。有关此算法的任何想法,以搜索可用的相邻席位?

此致

卡米洛

3 个答案:

答案 0 :(得分:5)

您可以通过在Column = Column + 1:

上连接表格aginst来获得两个相邻的席位
SELECT ...
FROM Seats A
JOIN Seats B ON A.Row = B.Row AND A.Column = B.Column+1
WHERE A.IsReserved = 0
AND B.IsReserved = 0

您可以通过在Column = Column + 1,+ 2,+ 3上重复连接将其扩展到3-4个座位链。如果你想要任何序列长度的更通用的解决方案,你将不得不使用递归CTE并且它变得复杂。对于大多数用例,简单连接都可以正常工作。

例如:

create table Seats (Row int not null
  , Col int not null
  , IsReserved bit not null
  , constraint pkSeatsRowColumn primary key (Row, Col));
go
insert into Seats (Row, Col, IsReserved)
select 1,1,0 union all
select 1,2,0 union all
select 1,3,1 union all
select 1,4,0 union all
select 1,5,0 union all
select 1,6,0 union all
select 2,1,0;

with cteAnchor as (
  SELECT Row, Col, 1 as [length]
  FROM Seats
  WHERE IsReserved = 0)
, cteRecursive as (
  SELECT Row, Col, [length]
  FROM cteAnchor
  UNION ALL
  SELECT c.Row, c.Col, c.[length]+1
  FROM Seats s
  JOIN cteRecursive c
    ON s.Row = c.Row and s.Col = c.Col+c.[length]
  WHERE s.IsReserved = 0)
select * from cteRecursive 

递归查询将返回包含起始座位编号和序列长度的集合中的所有可用座位序列。如果只需要长度为3的序列,则添加必要的WHERE子句,查询将返回座位(1,4),这是我的样本数据中唯一一个旁边有2个可用座位的席位。

答案 1 :(得分:1)

CREATE TABLE #Places(LineNumber INT, ColumnNumber INT, IsOccupied CHAR(1));
GO

DECLARE @NumAdjacent INT;

SET @NumAdjacent = 3;

SELECT * FROM #Places AS p
WHERE @NumAdjacent = (SELECT COUNT(*) FROM #Places AS p1
 WHERE p1.LineNumber = p.LineNumber
 AND p1.ColumnNumber BETWEEN p.ColumnNumber AND p.ColumnNumber + @NumAdjacent - 1
 AND p1.IsOccupied = 'Y');

答案 2 :(得分:0)

WITH    places AS
        (
        SELECT   1 AS row, 1 AS col, 0 AS occupied
        UNION ALL
        SELECT   1 AS row, 2 AS col, 1 AS occupied
        UNION ALL
        SELECT   1 AS row, 3 AS col, 0 AS occupied
        UNION ALL
        SELECT   1 AS row, 4 AS col, 0 AS occupied
        UNION ALL
        SELECT   1 AS row, 5 AS col, 0 AS occupied
        UNION ALL
        SELECT   1 AS row, 6 AS col, 1 AS occupied
        )
SELECT  row, col, len
FROM    (
        SELECT  row, col, COUNT(*) OVER (PARTITION BY row, span) AS len
        FROM    (        
                SELECT  row, col,
                        col - ROW_NUMBER() OVER (PARTITION BY row ORDER BY col) AS span
                FROM    places
                WHERE   occupied = 0
                ) q
        ) q2
WHERE   len >= 3

此查询返回3个或更多地方的所有免费范围。

这里的基本想法是column是连续的,尽管所有席位和ROW_NUMBER只在免费席位内是连续的:

column  occupied  ROW_NUMBER  diff
1       0         1           0
2       1         -           -
3       0         2           1
4       0         3           1
5       0         4           1
6       1         -           -

免费席位的范围在columnROW_NUMBER之间具有相同的差异,并且可以使用此差异对其进行分组。