首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> SQL Server 2008

使用 SQL Server 2008 R2 透過 T-SQL 邏輯推理解決「五人住五樓層」經典邏輯謎題

     編輯:SQL Server 2008

本文展示如何在 SQL Server 2008 R2 環境下,純粹使用 T-SQL 的集合運算 (CTE 遞迴產生排列組合) 與字串模式比對,解決經典邏輯謎題:Baker、Cooper、Fletcher、Miller、Smith 住在五層樓的不同樓層,依條件推導各人樓層。

題目條件整理

  • 五人對應代碼:A=Baker, B=Cooper, C=Fletcher, D=Miller, E=Smith
  • Baker 不住頂樓 (第 5 樓)
  • Cooper 不住底樓 (第 1 樓)
  • Fletcher 不住頂樓、不住底樓
  • Miller 樓層高於 Cooper (D 在 B 之後)
  • Smith 與 Fletcher 不相鄰 (E 不與 C 相鄰)
  • Fletcher 與 Cooper 不相鄰 (C 不與 B 相鄰)

解題思路:三階段 Pipeline

  1. 基礎資料準備:建立代碼對照表。
  2. 產生所有排列組合:使用遞迴 CTE 產生 5! = 120 種排列。
  3. 套用條件篩選:用 SUBSTRING、LIKE 模式比對過濾符合所有條件的排列。

完整 T-SQL 程式碼

1. 建立代碼對照表

CREATE TABLE #ttb (subname CHAR(1), realname VARCHAR(10));
INSERT INTO #ttb VALUES 
('A','Baker'),('B','Cooper'),('C','Fletcher'),('D','Miller'),('E','Smith');

2. 遞迴 CTE 產生全排列 (長度 5、不重複字元)

WITH x0 AS (
    SELECT CONVERT(VARCHAR(10), 'A') AS hid UNION ALL
    SELECT 'B' UNION ALL SELECT 'C' UNION ALL SELECT 'D' UNION ALL SELECT 'E'
),
x1 AS (
    SELECT hid FROM x0 WHERE LEN(hid) <= 5
    UNION ALL
    SELECT CONVERT(VARCHAR(10), a.hid + b.hid)
    FROM x0 a INNER JOIN x1 b ON CHARINDEX(a.hid, b.hid, 1) = 0
)
SELECT hid AS name INTO #tt FROM x1 WHERE LEN(hid) = 5 ORDER BY hid;

3. 套用邏輯條件篩選並輸出樓層與姓名

WITH x2 AS (
    SELECT name FROM #tt
    WHERE SUBSTRING(name, 5, 1) <> 'A'                     -- Baker 不住頂樓
      AND SUBSTRING(name, 1, 1) <> 'B'                     -- Cooper 不住底樓
      AND SUBSTRING(name, 1, 1) <> 'C' AND SUBSTRING(name, 5, 1) <> 'C'  -- Fletcher 不住首尾
      AND name LIKE '%B%D%'                                -- Miller 在 Cooper 之上 (D 在 B 後)
      AND name NOT LIKE '%CE%' AND name NOT LIKE '%EC%'    -- Smith 與 Fletcher 不相鄰
      AND name NOT LIKE '%BC%' AND name NOT LIKE '%CB%'    -- Fletcher 與 Cooper 不相鄰
),
x3 AS (
    SELECT number AS floor, SUBSTRING(x2.name, number, 1) AS code
    FROM master.dbo.spt_values
    INNER JOIN x2 ON 1=1
    WHERE type = 'P' AND number BETWEEN 1 AND 5
)
SELECT x3.floor AS 樓層, t.realname AS 姓名
FROM x3 INNER JOIN #ttb t ON t.subname = x3.code
ORDER BY x3.floor;

執行結果

唯一解:

樓層姓名
1Cooper
2Baker
3Fletcher
4Miller
5Smith

查詢結果畫面

關鍵技術點說明

  • 遞迴 CTE (x0 → x1):在不支援 GENERATE_SERIES 或 PERMUTATION 內建函數的舊版 SQL Server 中,利用 CHARINDEX 排除已用字元,逐層疊加字串產生全排列。
  • 字串模式比對:SUBSTRING(name, position, 1) 取特定樓層代碼;LIKE '%B%D%' 表示 D 在 B 之後 (不一定相鄰);NOT LIKE '%CE%' 排除相鄰組合。
  • master.dbo.spt_values:系統資料表作為數字產生器 (type='P' 為 0-2047),配合 BETWEEN 1 AND 5 產生樓層號 1-5,再將排列字串逐字元拆解對應。

延伸應用

此模式可應用於:

  • 排程/排班問題 (人員、時段、限制條件)
  • 資源分配組合搜尋
  • 小規模組合優化問題 (n ≤ 8 時全排列尚在可接受範圍)
對於大規模組合問題,建議改用專屬最佳化演算法 (CP-SAT、遺傳演算法) 或外部程式 (Python OR-Tools) 求解,T-SQL 集合運算較適合中小規模邏輯推理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved