2009-12-28 207 views
3

表示,如何选择相邻的座位?座位图

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

问候,

卡米洛

+0

听起来像一个有趣的问题。有一个示例表?不速之客,我正在考虑与座位空间完全充实的桌子进行连接。 (即加入部分销售的公共汽车/火车/飞机与完全售出的公交车/火车/飞机,显示座位排,满足您最低的座位标准,然后筛选座位邻接度。) – 2009-12-28 21:29:46

回答

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 s为连续的,虽然所有的座椅和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   -   - 

的免费席位的跨度有column之间的相同的差异而ROW_NUMBER和这个区别可以用来对它们进行分组。

4

您可以通过在柱接合表aginst本身得到两个相邻的座椅=柱+ 1:

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 

可以扩展这个3-4座椅通过在Column = Column + 1,+ 2,+3上重复连接来链接。如果你想为任何序列长度提供更通用的解决方案,你将不得不使用递归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 

递归查询将返回所有可用的座位的序列在包含起始座位号和sequnce的长度的一组。如果您只想要长度为3的序列,则需要添加必要的WHERE子句,并且查询将返回座位(1,4),这是我的示例数据中唯一具有2个可用座位的座位。

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'); 
+1

这将返回所有最终排座位,因为'不存在'的条件将会被'虚假'的座位所满足。 – 2009-12-28 21:47:35

+0

您可以在子查询中使用COUNT。如果col和col + @ num之间的*现有*免费座位的数量恰好是@num,则表示匹配。 – 2009-12-28 21:50:56

+0

Remus,我同意。谢谢! – 2009-12-28 22:54:05