简体   繁体   English

在MySQL中检索组的第一个值?

[英]Retrieve first value of group in MySQL?

How can I get the first non-empty-value of a group in MySQL? 如何获取MySQL中组的第一个非空值?

I have the following table: 我有下表:

id | item_id | name         | description        | locale
----------------------------------------------------------
1  | 1       |     (null)   |       (null)       | en-GB
2  | 1       | Foo          |       (null)       | en-US
3  | 1       | Bar          | Lorem ipsum dolor. | en-AU

I'm trying to return a result like the following?: 我正在尝试返回如下结果:

item_id | name         | description
-------------------------------------------------------------------
1       | Foo          | Lorem ipsum dolor.

I am told coalsece was the way to go but it doesn't seem to play with groups. 有人告诉我coalsece是必经之路,但似乎不适合与团体合作。 Although the shot didn't fire correctly. 虽然镜头无法正确发射。 It should give a good picture of what I'm trying to do. 它应该可以很好地说明我要做什么。

select item_id, coalesce(name) as name, coalesce(description) as description from test
where item_id = 1
group by item_id
order by field(locale, 'en-GB', 'en-US', 'en-AU');

Other attempts where made using first(), first_value(), min(), max()... I rather accomplish this in a straight MySQL query than mix it with PHP logic. 使用first(),first_value(),min(),max()进行其他尝试...我宁愿在直接的MySQL查询中完成此操作,也不愿将其与PHP逻辑混合使用。

You can try something like this: 您可以尝试如下操作:

select 
    item_id,

    substring_index(
        coalesce(group_concat(name separator ','), ''), 
        ',', 
        1
    ) as first_name,

    substring_index(
        coalesce(group_concat(description separator ','), ''), 
        ',', 
        1
   ) as first_description

from test
group by item_id

See note at the bottom regarding order by . 请参阅底部的注释,了解有关order by

Result 结果

item_id first_name  first_description
1       Foo         Lorem ipsum dolor.
2       

Explanation 说明

Using group_concat function, we are combining all the names and descriptions into a CSV for each item_id. 使用group_concat函数,我们将每个item_id的所有名称和描述组合到CSV中。

The result could be null. 结果可能为空。 So we use coalesce to supply an empty string as the value if group_concat resulted in null. 因此,如果group_concat结果为null,则使用coalesce提供一个空字符串作为值。

Then we split by comma and get the first piece of information. 然后,我们用逗号分隔并获得第一条信息。

The caveat is that your name or description may contain a comma. 请注意,您的姓名或描述可能包含逗号。 You will have to account for that somehow, which the query about does not currently. 您将必须以某种方式解决该问题,而该查询当前尚不存在。

Live Example or data to try out, if someone wants to 现场示例或数据尝试,如果有人想

http://rextester.com/RFI82565 http://rextester.com/RFI82565

create table test (
  id int,
  item_id int, 
  name varchar(100),
  description varchar(200),
  locale varchar(10)
);

insert into test values 
(1, 1, NULL, NULL, 'en-GB'),
(2, 1, 'Foo', NULL, 'en-US'),
(3, 1, 'Bar', 'Lorem ipsum dolor.', 'en-AU'),
(4, 2, NULL, NULL, 'en-GB');

Note 注意

User strawberry noted wisely that my query was missing an order by clause, which OP may find valuable. 用户Strawberry明智地指出,我的查询缺少order by子句,OP可能会发现它有价值。

Ordering can be done in the group_concat clause and after group by clause. 排序可以在group_concat子句中以及在group by子句之后group by Below is an example of how ordering can be done at both levels. 以下是如何在两个级别上进行订购的示例。 Ordering at group_concat level orders ensures that the first_name is based on the order you provided. group_concat级别的订单进行订购可确保first_name基于您提供的订单。 Ordering after group by helps the resulting output to be ordered. group by之后的排序有助于对输出结果进行排序。

select 
    item_id,

    substring_index(
        coalesce(group_concat(name order by field(locale, 'en-GB', 'en-US', 'en-AU') separator ','), ''), 
        ',', 
        1
    ) as first_name,

    substring_index(
        coalesce(group_concat(description order by field(locale, 'en-GB', 'en-US', 'en-AU') separator ','), ''), 
        ',', 
        1
   ) as first_description

from test
group by item_id
order by field(locale, 'en-GB', 'en-US', 'en-AU');

Similar to @zedfoxus's solution, but using a Standard SQL solution working in every DBMS: 与@zedfoxus的解决方案类似,但是在每个DBMS中都使用标准SQL解决方案:

select 
    item_id,

    coalesce(max(case when locale = 'en-GB' then name end)
            ,max(case when locale = 'en-US' then name end)
            ,max(case when locale = 'en-AU' then name end)) as first_name,

    coalesce(max(case when locale = 'en-GB' then description end)
            ,max(case when locale = 'en-US' then description end)
            ,max(case when locale = 'en-AU' then description end)) as first_description

from test
group by item_id
select TT2.Id, TT2.Item_Id, TT2.MyName, TT2.MyDesc, TT2.Locale from #TempTest TT2 
where convert(Varchar(12),TT2.Id) + '#' + convert(Varchar(12),TT2.Item_Id) 
in 
(
select X = convert(Varchar(12),Min(TT1.Id)) + '#' + convert(Varchar(12),Min(TT1.Item_Id))
from #TempTest TT1
where TT1.MyName is not null
group by TT1.Locale
)

Im not sure but I think the following query will retrieve only the field where there are no null values 我不确定,但我认为以下查询将仅检索没有空值的字段

 SELECT item_id,name,description,locale FROM test WHERE (name != '' AND description != '')

Hope it works 希望能奏效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM