用另一条记录的结果替换空/空字符串
Posted
技术标签:
【中文标题】用另一条记录的结果替换空/空字符串【英文标题】:Replace empty/null string with result from another record 【发布时间】:2013-12-06 17:40:55 【问题描述】:我有一个语言表,想要检索所选语言的特定记录。但是,当没有翻译时,我想获得另一种语言的翻译。
翻译
TAG LANG TEXT
"prog1" | 1 | "Programmeur"
"prog1" | 2 | "Programmer"
"prog1" | 3 | "Programista"
"prog2" | 1 | ""
"prog2" | 2 | "Category"
"prog2" | 3 | "Kategoria"
"prog3" | 1 | "Actie"
"prog3" | 2 | "Action"
"prog3" | 3 | "Dzialanie"
程序数据
ID | COL1 | COL2
1 | "data" | "data"
2 | "data" | "data"
3 | "data" | "data"
如果我想根据表 PROGDATA 中的 ID 翻译语言 3,那么我可以这样做:
SELECT TEXT FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=3
这会给我:“Programista”“Kategoria”“Dzialanie”
如果是语言 1,我在第二条记录上得到一个空字符串:"Programmeur""""演员”
如何将空字符串替换为例如语言 2 的翻译?“Programmeur”“Category”“行动”
我尝试在IIf()
函数中嵌套一个新的选择查询,但这显然不起作用。
SELECT
IIf(TEXT="",
(SELECT TEXT FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=2),TEXT)
FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=3
【问题讨论】:
如果首选语言不可用,如何选择使用哪种语言? 始终填充默认语言,例如这可能是语言 2。无论如何,它是硬编码的。 如果未填充默认语言,则这是开发人员错误;)在这种情况下,我应该生成错误(但是,我将在 SQL 之外执行此操作)。 【参考方案1】:SWITCH
或 CASE
语句可能效果很好。但是试试这个:
SELECT
IIf(TEXT="",
(SELECT TEXT AS TEXT_OTHER FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=2),TEXT) AS TEXT_FINAL
我使用TEXTOTHER
和TEXTFINAL
来减少字段名称的歧义。有时这会有所帮助。
您甚至可能需要将该原则应用于表名:
(SELECT TEXT AS TEXT_OTHER FROM TRANSLATIONS AS TRANSLATIONS_ALT...
另外,请确保您的标准是正确的:空字符串,而不是 Null 值。
IIf(TEXT="", ...
IIf(ISNULL(TEXT), ...
【讨论】:
我无法让它在 Access 中工作。 “子查询 'TEXT' 中的无效备注、OLE 或超链接对象”。这可能是因为子查询返回多个结果。所以我尝试比较第一个和第二个查询的 TAG:TRANSLATIONS_ALT.TAG = TRANSLATIONS_MAIN.TAG。然而,这并没有帮助。【参考方案2】:您可以再次加入 TRANSLATIONS 表以获得“默认”翻译并在 SELECT 语句中使用 CASE。
SELECT
CASE
WHEN ISNULL(Translation.TEXT,"") = "" THEN DefaultLang.TEXT
ELSE Translation.Text
END
FROM TRANSLATIONS AS DefaultLang,TRANSLATIONS as Translation, PROGDATA
WHERE
DefaultLang.TAG="prog" & PROGDATA.ID AND Translation.TAG="prog" & PROGDATA.ID
AND DefaultLang.LANG=2
AND Translation.LANG=3
【讨论】:
Access 为此目的使用Nz()
; IsNull()
仅返回 True 或 False。但是,由于 Access 的引擎首选项,建议构建 Iif()
语句而不是使用 Nz()
。见allenbrowne.com/QueryPerfIssue.html#nz
显然,MS Access 中没有 CASE 语句。 ***.com/questions/772461/case-statement-in-access
你必须使用 IIf()【参考方案3】:
这是一个伪代码的想法... 我会尝试为返回的每个值添加一个 checkEmpty 函数。如果不为空,则返回相同的内容。如果为空,则从其他语言返回新的搜索。 当然,您需要再次检查新值是否为空。
create function checkEmpty( @word varchar(10), @languageNumber integer) returns varchar(10)
as
begin
declare @newWord
declare @newlanguage
if @word <> '' then return @word else
begin
//select new language
case languageNumber of
3 then @newlanguage = 1;
2 then @newlanguage = 3;
1 then @newlanguage = 2;
//search new lenguage
@newWord= SELECT TEXT FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=@newlanguage
return @newWord
end;
end;
//函数调用
SELECT dbo.checkEmpty(TEXT) FROM TRANSLATIONS, PROGDATA
WHERE TRANSLATIONS.TAG="prog" & PROGDATA.ID
AND TRANSLATIONS.LANG=3
【讨论】:
从 Access 查询中调用 VBA 函数会导致效率问题,更重要的是在大多数情况下会导致代码可维护性问题。因此,不能通过诸如已接受的直接 SQL 解决方案来推荐此方法。然而,这是一个有创意且可行的想法。【参考方案4】:我将@fossilcoder 和@Smandoli 的解决方案合并为一个解决方案:
SELECT
IIf (
NZ(TRANSLATION.Text,"") = "", DEFAULT.TEXT, TRANSLATION.TEXT)
FROM
TRANSLATIONS AS TRANSLATION,
TRANSLATIONS AS DEFAULT,
PROGDATA
WHERE
TRANSLATION.Tag="prog_" & PROGDATA.Id
AND
DEFAULT.Tag="prog" & PROGDATA.Id
AND
TRANSLATION.LanguageId=1
AND
DEFAULT.LanguageId=2
我从没想过以不同的别名引用一个表两次
【讨论】:
当您可以直接使用 NZ(或 ISNULL)时,为什么要使用 IF? ....选择新西兰(翻译.文本,默认.文本).... NZ(TRANSLATION.Text,"") = "" 是双重检查。它首先检查 NULL,然后检查空字符串。当 TRANSLATION 为 NULL 或 "" 时应使用 DEFAULT以上是关于用另一条记录的结果替换空/空字符串的主要内容,如果未能解决你的问题,请参考以下文章