如何获得MySQL中组的第一个非空值?

我有下表:

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


我正在尝试返回如下结果:

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


有人告诉我coalsece是必经之路,但似乎不适合与团体合作。虽然镜头无法正确发射。它应该可以很好地说明我要做什么。

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');


使用first(),first_value(),min(),max()进行其他尝试...我宁愿在直接的MySQL查询中完成此操作,也不愿将其与PHP逻辑混合使用。

最佳答案

您可以尝试如下操作:

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


请参阅底部有关order by的注释。

结果

item_id first_name  first_description
1       Foo         Lorem ipsum dolor.
2


说明

使用group_concat函数,我们将每个item_id的所有名称和描述组合到CSV中。

结果可能为空。因此,如果coalesce结果为null,则使用group_concat提供一个空字符串作为值。

然后,我们用逗号分隔并获得第一条信息。

请注意,您的姓名或描述可能包含逗号。您将必须以某种方式解决该问题,而该查询当前尚不存在。

现场示例或数据尝试,如果有人想

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');


注意

草莓用户明智地指出,我的查询缺少一个order by子句,OP可能认为这很有用。

可以在group_concat子句中和group by子句之后进行排序。以下是如何在两个级别上进行订购的示例。以group_concat级订单进行订购可确保first_name基于您提供的订单。在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');

08-24 17:46
查看更多