2009-12-28 209 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