每个COLUMN值选择一行

时间:2017-09-11 18:57:39

标签: mysql

我有一张这样的表:

id  |  subscriber_id  |  var_name  |  var_value        | created
1   |  35             |  last_name |  Smith            | [TIMESTAMP]
2   |  35             |  city      |  New York         | [TIMESTAMP]
3   |  35             |  city      |  Boston           | [TIMESTAMP]

在这种情况下,假设var_value=Boston的行时间戳晚于var_value=New York行,因此我们将选择Boston行。

我尝试过这样的事情,但有时会说非聚合列分组。

      SELECT
        var_name, var_value
      FROM
        subscriber_vars
      WHERE
        subscriber = ?
      GROUP BY subscriber
      ORDER BY
        created DESC

所以在这种情况下,预期的输出是:

[
    'last_name'  =>  'Smith'
    'city'       =>  'Boston'
]

2 个答案:

答案 0 :(得分:2)

使用GROUP BY

SELECT * FROM (
    SELECT var_name, var_value FROM subscriber_vars ORDER BY created DESC
) x
GROUP BY var_name

GROUP BY将仅选择给定结果集中第一个唯一值的值,其顺序与结果行的顺序相同。

因此,我们运行一个查询来获取和排序我们想要的信息(SELECT var_name, var_value FROM subscriber_vars ORDER BY created DESC),然后对查询返回的结果运行GROUP BY

现在,我们按照我们想要的顺序为我们提供了一组行,其中包含我们想要的列,其中只包含第一次出现的var_name值。

现在,我们只需要SELECT所有这些行返回它们,这就是SELECT * FROM部分的用途。

备注

请查看此StackOverflow post以进一步阅读。

答案 1 :(得分:-1)

如果您对以这种方式存储的数据量相当受限,并且列已正确编入索引,则以下查询应该有效:

select l.`last_name`, c.`city` from 
(SELECT subscriber_id, var_value as `city` FROM subscriber_vars WHERE var_name='city' ORDER BY created DESC LIMIT 1) c 
join 
(SELECT subscriber_id, var_value as `last_name` FROM subscriber_vars WHERE var_name='last_name' ORDER BY created DESC LIMIT 1) l USING(subscriber_id) 
where c.subscriber_id = 35;

返回的数据应如下所示:

last_name |city
Smith     |Boston