LIKE '%kw%' 結果隨機。需**關鍵字出現頻率加權排序** (類 TF-IDF 簡化版)。
CREATE FUNCTION dbo.WordCount (@Word VARCHAR(15), @Phrase VARCHAR(1000))
RETURNS SMALLINT AS BEGIN
IF @Word IS NULL OR @Phrase IS NULL RETURN 0;
DECLARE @BiggerWord VARCHAR(21) = @Word + 'x'; -- 比關鍵字長 1 字元
DECLARE @BiggerPhrase VARCHAR(2000) = REPLACE(@Phrase, @Word, @BiggerWord);
RETURN LEN(@BiggerPhrase) - LEN(@Phrase); -- 長度差 = 出現次數
END
**高效原理:** 單次 REPLACE + 長度差運算,**無迴圈、無游標**,集合式運算極快。
SELECT Name,
3 * dbo.WordCount(@Word1, Name) + dbo.WordCount(@Word1, Description)
+ 3 * dbo.WordCount(@Word2, Name) + dbo.WordCount(@Word2, Description)
+ ... AS Rank
FROM Product
ORDER BY Rank DESC;
Name 權重 3,Description 權重 1 (可依業務調整)。
SELECT Name,
(3*WC(@W1,Name)+WC(@W1,Desc)) *
CASE WHEN @W2 IS NULL THEN 1 ELSE 3*WC(@W2,Name)+WC(@W2,Desc) END *
CASE WHEN @W3 IS NULL THEN 1 ELSE ... END
... AS Rank
FROM Product
ORDER BY Rank DESC;
替代寫法:未出現詞給 -1000 權重 → Rank 為負 → 過濾。
DECLARE @Products TABLE (
RowNumber SMALLINT IDENTITY(1,1),
ID INT, Name VARCHAR(50), Description VARCHAR(1000), Rank INT
);
-- 插入排序後結果
INSERT INTO @Products ... ORDER BY Rank DESC;
-- 取總數
SELECT @HowManyResults = COUNT(*) FROM @Products WHERE Rank > 0;
-- 分頁回傳
SELECT * FROM @Products
WHERE Rank > 0
AND RowNumber BETWEEN (@PageNumber-1)*@ProductsPerPage+1 AND @PageNumber*@ProductsPerPage
ORDER BY Rank DESC;
CREATE PROCEDURE SearchCatalog
@PageNumber TINYINT,
@ProductsPerPage TINYINT,
@HowManyResults SMALLINT OUTPUT,
@AllWords BIT, -- 1=ALL, 0=ANY
@Word1 VARCHAR(15)=NULL, @Word2 VARCHAR(15)=NULL, @Word3 VARCHAR(15)=NULL,
@Word4 VARCHAR(15)=NULL, @Word5 VARCHAR(15)=NULL
AS
BEGIN
-- 1. 依 @AllWords 分支 INSERT 到 @Products (含 Rank 計算)
-- 2. 統計 @HowManyResults
-- 3. 分頁 SELECT 回傳
END
**核心亮點:** UDF 高效計頻、權重靈活配置、ALL/ANY 邏輯清晰分離、資料層分頁避免海量資料傳輸。可直接擴展為生產級搜尋服務。