3

我需要使用“近匹配”进行 JOIN。解释这一点的最好方法是举个例子:

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)

SPROC 看起来像这样:

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”没有值)。

4

2 回答 2

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
于 2012-10-20T15:41:23.503 回答
1

正如@Roman Pekar 在他的评论中所说,这确实可以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仅包括LanguageCode值为@LanguageCodeLEFT(@LanguageCode, 2)和的行'en'

  2. 排名值是根据每行包含的语言代码分配的:具有的行在具有的行之后但在具有的行之前LEFT(@LanguageCode, 2)排名。@LanguageCode'en'

于 2012-10-21T21:30:25.423 回答