2012-10-20 43 views
3

我需要通過'near match'加入。解釋這一點的最好辦法是用一個例子:SQL:與'near'匹配加入

CREATE TABLE Car 
(
Vin int, 
Make nvarchar(50), 
ColorID int, 
) 

CREATE TABLE Color 
(
ColorID int, 
ColorCode nvarchar(10) 
) 

CREATE TABLE ColorName 
(
ColorID int, 
Languagecode varchar(12), 
ColorName nvarchar(50) 
) 

INSERT INTO Color Values (1, 'RED CODE') 
INSERT INTO Color Values (2, 'GREEN CODE') 
INSERT INTO Color Values (3, 'BLUE CODE') 

INSERT INTO ColorName Values (1, 'en', 'Red') 
INSERT INTO ColorName Values (1, 'en-US', 'Red, my friend') 
INSERT INTO ColorName Values (1, 'en-GB', 'Red, my dear') 
INSERT INTO ColorName Values (1, 'en-AU', 'Red, mate') 
INSERT INTO ColorName Values (1, 'fr', 'Rouge') 
INSERT INTO ColorName Values (1, 'fr-BE', 'Rouge, mon ami') 
INSERT INTO ColorName Values (1, 'fr-CA', 'Rouge, mon chum') 

INSERT INTO Car Values (123, 'Honda', 1) 

的存儲過程是這樣的:

DECLARE @LanguageCode varchar(12) = 'en-US' 

SELECT * FROM Car A 
JOIN Color B ON (A.ColorID = B.ColorID) 
LEFT JOIN ColorName C ON (B.ColorID = C.ColorID AND C.LanguageCode = @LanguageCode) 

http://sqlfiddle.com/#!6/ac24d/24

這裏是挑戰(感謝傑克!): 當SPROC參數@LanguageCode完全匹配時,一切正常。

我希望它也適用於部分匹配;更具體地說:例如說@LanguageCode是'en-NZ',那麼我希望SPROC返回語言代碼'en'的值(因爲'en-NZ'沒有值)。

作爲額外的挑戰:如果根本沒有匹配,我想返回'en'值;例如,如果@LanguageCode是'es',那麼SPROC將返回'en'值(因爲'es'沒有值)。

回答

1

正如@羅曼·派卡爾在his comment中所說的那樣,這確實可以在一個語句中藉助排名功能完​​成,包括您關於回落到en的額外請求。你可以這樣做:

WITH FilteredAndRanked AS (
    SELECT 
    *, 
    rnk = ROW_NUMBER() OVER (
     PARTITION BY ColorID 
     ORDER BY CASE LanguageCode 
     WHEN @LanguageCode   THEN 1 
     WHEN LEFT(@LanguageCode, 2) THEN 2 
     WHEN 'en'     THEN 3 
     END 
    ) 
    FROM ColorName 
    WHERE LanguageCode IN (
    @LanguageCode, 
    LEFT(@LanguageCode, 2), 
    'en' 
) 
) 
SELECT 
    ... 
FROM  Car    A 
INNER JOIN Color    B ON (A.ColorID = B.ColorID) 
LEFT JOIN FilteredAndRanked C ON (B.ColorID = C.ColorID AND C.rnk = 1) 

;

即,ColorName表被過濾並且排在查詢中使用之前,然後只用1排名的行接合:

  1. ColorName該過濾器包括唯一的行與LanguageCodeLEFT(@LanguageCode, 2)'en'的值。

  2. 根據每行包含的語言代碼來分配排名值:LEFT(@LanguageCode, 2)的行排在之後但'en'之後。

+0

非常感謝。我不知道「排名功能」。 –

2

嘗試left(@LanguageCode, 2) + '%'

http://sqlfiddle.com/#!6/ac24d/26

關於第二部分 - 你要查詢表兩次呢(你可以做一個聲明,但如果會像一個兩個語句)。您也可以將數據插入臨時(或變量)表,檢查是否有任何行,然後再次查詢

我已經和表函數查詢

http://sqlfiddle.com/#!6/b7be3/5

所以,你可以寫

DECLARE @LanguageCode varchar(12) = 'es' 

if not exists (select * from sf_test(@LanguageCode)) 
    select * from sf_test('en') 
else 
    select * from sf_test(@LanguageCode) 

你也可以寫

declare @temp table 
(
    Vin int, 
    Make nvarchar(50), 
    ColorCode nvarchar(10) 
) 

insert into @temp 
select * from sf_test(@LanguageCode) 

if not exists (select * from @temp) 
    select * from sf_test('en') 
else 
    select * from @temp 
+0

謝謝但左(@LanguageCode,2)+'%'不符合我的要求。請參閱http://sqlfiddle.com/#!6/ac24d/27。使用'en-NZ'時,SPROC應該只返回一行,最好的匹配是'en'行(因爲沒有'en-NZ'行)[並且不是所有以'en'開頭的行爲你的解決方案]。 –

+0

好吧,我想我不明白你的任務。試試這個http://sqlfiddle.com/#!6/d803f/3。如果你真的需要它,我也認爲可以在一個語句中使用一些排名功能來完成 –