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.
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. 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:
Explanation:
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).The “trick” here is using mysql’s “non-standard”
GROUP BYbehaviour 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. The outer select usesgroup bywithout an aggregate to get the first row for each named group by.Output of this query using your data: