[英]select * from table where column = something or, when unavailable, column = something else
I am looking for something more efficient and/or easier to read than the query that follows. 我正在寻找比随后的查询更有效和/或更容易阅读的东西。 The best way to explain the question is to provide a sample.
解释问题的最好方法是提供样本。
Assume the following table structure in MySQL that represents, say, a localization context for various strings in the application I am creating. 假设MySQL中的以下表结构代表了我正在创建的应用程序中各种字符串的本地化上下文。
create table LOCALIZATION_TABLE (
SET_NAME varchar(36) not null,
LOCALE varchar(8) not null default '_',
ENTRY_KEY varhcar(36) not null,
ENTRY_VALUE text null
);
alter table LOCALIZATION_TABLE
add constraint UQ_ENTRY
unique (SET_NAME, LOCALE, ENTRY_KEY);
Assume the following values are entered in the table: 假设在表中输入了以下值:
insert into LOCALIZATION_TABLE (SET_NAME, LOCALE, ENTRY_KEY, ENTRY_VALUE)
values
('STD_TEXT', '_', 'HELLO', 'Hello!'),
('STD_TEXT', '_', 'GOODBYE', 'Goodbye.'),
('STD_TEXT', 'ge', 'GOODBYE', 'Lebewohl')
;
I want to select all the available entries for German ("ge"), and if not available use the English text ("_") by default. 我想选择德语(“ ge”)的所有可用条目,如果不可用,则默认使用英文文本(“ _”)。 The query I am currently using is as follows:
我当前使用的查询如下:
select * from LOCALIZATION_TABLE where SET_NAME = 'STD_TEXT' and LOCALE = 'ge'
union
select * from LOCALIZATION_TABLE where SET_NAME = 'STD_TEXT' and LOCALE = '_'
and ENTRY_KEY not in (
select ENTRY_KEY from LOCALIZATION_TABLE where BUNDLE = 'STD_TEXT' and LOCALE = 'ge'
)
I really do not like the look of this query and I am certain there must be something more concise that can be utilized instead. 我真的不喜欢该查询的外观,并且我肯定必须使用一些更简洁的方法。 Any help or clues to the right direction would be appreciated.
任何帮助或正确方向的线索将不胜感激。 While this works it just does not seem proper .
尽管这行得通,但似乎不合适 。
You can provide a custom ordering, then take the first row, like this: 您可以提供自定义排序,然后选择第一行,如下所示:
select * from (
select *
from LOCALIZATION_TABLE
where SET_NAME = 'STD_TEXT'
order by field(LOCALE, 'ge', '_') -- this provides the custom ordering
) x
group by ENTRY_KEY; -- this captures the first row for each ENTRY_KEY
The inner select's order by field(LOCALE, 'ge', '_')
gets you the rows in the order you define - in this case German first if it exists, then English (you could add more languages to the list). 内部选择
order by field(LOCALE, 'ge', '_')
的order by field(LOCALE, 'ge', '_')
将按您定义的顺序获取行-在这种情况下,如果存在的话,首先显示德语,然后显示英语(您可以在列表中添加更多语言)。
The "trick" here is using mysql's "non-standard" GROUP BY
behaviour when not listing the non-group columns (most servers treat this as a syntax error) - it simply returns the first row found for every group. 当不列出非组列时(大多数服务器将其视为语法错误),此处的“技巧”是使用mysql的“非标准”
GROUP BY
行为-它仅返回为每个组找到的第一行。 The outer select uses group by
without an aggregate to get the first row for each named group by. 外部选择使用不带聚集的
group by
来获取每个命名group by的第一行 。
Output of this query using your data: 使用您的数据查询输出:
+----------+--------+-----------+-------------+
| SET_NAME | LOCALE | ENTRY_KEY | ENTRY_VALUE |
+----------+--------+-----------+-------------+
| STD_TEXT | ge | GOODBYE | Lebewohl |
| STD_TEXT | _ | HELLO | Hello! |
+----------+--------+-----------+-------------+
I think your query is fine. 我认为您的查询很好。 But here's another approach:
但是,这是另一种方法:
SELECT
en.SET_NAME
, COALESCE(ge.LOCALE, en.LOCALE)
, en.ENTRY_KEY
, COALESCE(ge.ENTRY_VALUE, en.ENTRY_VALUE)
FROM
LOCALIZATION_TABLE AS en
LEFT JOIN
LOCALIZATION_TABLE AS ge
ON ge.ENTRY_KEY = en.ENTRY_KEY
AND ge.LOCALE = 'ge'
AND ge.SET_NAME = 'STD_TEXT'
WHERE
en.LOCALE = '_'
AND en.SET_NAME = 'STD_TEXT'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.