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

时间:2016-09-04 01:55:53

标签: php mysql sql select subquery

如何在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逻辑混合。

4 个答案:

答案 0 :(得分:3)

您可以尝试这样的事情:

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。

结果可能为null。因此,如果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');

答案 1 :(得分:2)

与@ 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

答案 2 :(得分:0)

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
)

答案 3 :(得分:-1)

我不确定,但我认为以下查询只会检索没有空值的字段

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

希望它有效