Mysql 查询从左到右优先使用 IN 子句查找
Mysql query to find first using IN clause with preference from left to right
我有一个测试 table 包含列(id、标题、语言)
id: primary_key (auto-increment)
unique_key(综合)关于语言和标题
id
title
language
1
Japanese
JP
2
Australian
AU
3
English
EN
4
Hindi
HI
我想要一个基于多语言标准的 return 1 或 0 行的查询。
查询应该 return 语言优先级从左到右的结果,如果从左到右没有找到第一种语言的行,则依次查找第二种语言。
Use-case:
languages
result row_id
remarks
JP,HI
1
As JP found at id=1
HI,JP
4
As HI found at id=4
RU,AU
2
As AU found at id=2, no row with language=RU
PK,ST
no row
As no language has value PK or ST
这是我尝试在语言列上使用 FIELD
子句的自定义顺序:
SELECT id, title, language
FROM test WHERE language IN ('TH', 'AU','EN') ORDER BY
FIELD(LANGUAGE,'TH','AU','EN') LIMIT 1;
Expected/Actual 输出:
id
title
language
2
Australian
AU
我想知道有没有更好的方法(在性能和可读性方面)来实现这个use-case?
将语言列表转换为行集:
SELECT test.id, test.title, language
FROM test
JOIN (SELECT 'TH' language, 1 priority UNION ALL
SELECT 'AU' , 2 UNION ALL
SELECT 'EN' , 3 ) languages USING (language)
ORDER BY languages.priority LIMIT 1;
for 8+, the parameter format would be csv – Another coder
WITH RECURSIVE
parameter AS (
SELECT @languages_as_CSV CSV
),
languages AS (
SELECT SUBSTRING_INDEX(CSV, ',', 1) language,
SUBSTRING(CSV FROM 1 + LOCATE(',', CSV)) tail,
1 priority
FROM parameter
UNION ALL
SELECT SUBSTRING_INDEX(tail, ',', 1),
SUBSTRING(tail FROM 1 + LOCATE(',', tail))
FROM cte
WHERE tail <> ''
)
SELECT test.id, test.title, language
FROM test
JOIN languages USING (language)
ORDER BY languages.priority LIMIT 1;
即递归 CTE 解析 CSV 以分离值并添加优先级数据。然后执行相同的查询,并使用解析的行集代替静态语言列表。
@languages_as_CS
是为查询提供 CSV 语言列表的参数的占位符。
注意 - none 多余的字符。 'TH,AU,EN'
而不是 'TH, AU, EN'
.
看看这是否有帮助:
SELECT ...
WHERE FIND_IN_SET(language, languages)
ORDER BY FIND_IN_SET(language, languages)
如果没有匹配项,FIND_IN_SET 将 return 为空集,因此需要一些额外的东西来处理“0”的情况。
我有一个测试 table 包含列(id、标题、语言)
id: primary_key (auto-increment)
unique_key(综合)关于语言和标题
id | title | language |
---|---|---|
1 | Japanese | JP |
2 | Australian | AU |
3 | English | EN |
4 | Hindi | HI |
我想要一个基于多语言标准的 return 1 或 0 行的查询。
查询应该 return 语言优先级从左到右的结果,如果从左到右没有找到第一种语言的行,则依次查找第二种语言。
Use-case:
languages | result row_id | remarks |
---|---|---|
JP,HI | 1 | As JP found at id=1 |
HI,JP | 4 | As HI found at id=4 |
RU,AU | 2 | As AU found at id=2, no row with language=RU |
PK,ST | no row | As no language has value PK or ST |
这是我尝试在语言列上使用 FIELD
子句的自定义顺序:
SELECT id, title, language
FROM test WHERE language IN ('TH', 'AU','EN') ORDER BY
FIELD(LANGUAGE,'TH','AU','EN') LIMIT 1;
Expected/Actual 输出:
id | title | language |
---|---|---|
2 | Australian | AU |
我想知道有没有更好的方法(在性能和可读性方面)来实现这个use-case?
将语言列表转换为行集:
SELECT test.id, test.title, language
FROM test
JOIN (SELECT 'TH' language, 1 priority UNION ALL
SELECT 'AU' , 2 UNION ALL
SELECT 'EN' , 3 ) languages USING (language)
ORDER BY languages.priority LIMIT 1;
for 8+, the parameter format would be csv – Another coder
WITH RECURSIVE
parameter AS (
SELECT @languages_as_CSV CSV
),
languages AS (
SELECT SUBSTRING_INDEX(CSV, ',', 1) language,
SUBSTRING(CSV FROM 1 + LOCATE(',', CSV)) tail,
1 priority
FROM parameter
UNION ALL
SELECT SUBSTRING_INDEX(tail, ',', 1),
SUBSTRING(tail FROM 1 + LOCATE(',', tail))
FROM cte
WHERE tail <> ''
)
SELECT test.id, test.title, language
FROM test
JOIN languages USING (language)
ORDER BY languages.priority LIMIT 1;
即递归 CTE 解析 CSV 以分离值并添加优先级数据。然后执行相同的查询,并使用解析的行集代替静态语言列表。
@languages_as_CS
是为查询提供 CSV 语言列表的参数的占位符。
注意 - none 多余的字符。 'TH,AU,EN'
而不是 'TH, AU, EN'
.
看看这是否有帮助:
SELECT ...
WHERE FIND_IN_SET(language, languages)
ORDER BY FIND_IN_SET(language, languages)
如果没有匹配项,FIND_IN_SET 将 return 为空集,因此需要一些额外的东西来处理“0”的情况。