SQL。如何从 table 获取唯一值但仅限于 1 列?

SQL. How to obtain unique values from table but only for 1 column?

我有一个 table1。我按名称和时间列对 table 进行排序:

SELECT name, value 
FROM table1
WHERE time >= '2022-05-23 00:00:00' AND time <= '2022-05-23 01:00:00'  
ORDER BY name, time 

下一个我得到的结果 table :

    name,   value,  time
    A,      5,      2022-05-23 01:01:12
    A,      9,      2022-05-23 01:02:11
    A,      7,      2022-05-23 01:03:21
    B,      5,      2022-05-23 01:04:23
    B,      6,      2022-05-23 01:05:33
    C,      7,      2022-05-23 01:06:30
    C,      8,      2022-05-23 01:07:41
    C,      3,      2022-05-23 01:08:44
    C,      7,      2022-05-23 01:09:50

然后我需要 select 所有具有最短时间的唯一名称,并获得这些名称的值:

结果应该是这样的:

name,   value,  time
A,      5,      2022-05-23 01:01:12
B,      5,      2022-05-23 01:04:23
C,      7,      2022-05-23 01:06:30

============================================= ========================

事实证明,我们只是从 table:

中获取了每个第一个唯一名称
name,   value,  time
A,      5,      2022-05-23 01:01:12 <- take this one
A,      9,      2022-05-23 01:02:11
A,      7,      2022-05-23 01:03:21 
B,      5,      2022-05-23 01:04:23 <- take this one
B,      6,      2022-05-23 01:05:33
C,      7,      2022-05-23 01:06:30 <- take this one
C,      8,      2022-05-23 01:07:41
C,      3,      2022-05-23 01:08:44
C,      7,      2022-05-23 01:09:50

我的目标是使用时间戳最少的唯一名称(或 table 中的每个第一个唯一名称,因为它已经按时间戳排序)

我不清楚如何获得想要的结果。 我尝试使用“SELECT DISTINCT 名称,值”,但它返回所有唯一名称和唯一值,但我只需要唯一名称+值(时间最短的地方)

一般你会使用ROW_NUMBER,但是Clickhouse不支持解析函数。我们可以改用连接方法:

SELECT t1.*
FROM table1 t1
INNER JOIN
(
    SELECT name, MIN(time) AS min_time
    FROM table1
    WHERE time >= '2022-05-23 00:00:00' AND time <= '2022-05-23 01:00:00'
    GROUP BY name
) t2
    ON t2.name = t1.name AND
       t2.min_time = t1.time
WHERE
    time >= '2022-05-23 00:00:00' AND time <= '2022-05-23 01:00:00';

可以使用函数argMin聚合函数(https://clickhouse.com/docs/en/sql-reference/aggregate-functions/reference/argmin/) to achieve the desired result. If you need to get the latest row, there is the argMax aggregation function (https://clickhouse.com/docs/en/sql-reference/aggregate-functions/reference/argmax/)。

argMin/argMax 的想法是 return 给定值的最小值或最大值的参数(time,在您的用例中)。

示例数据:

select * from table1; 

SELECT *
FROM table1

┌─name─┬─value─┬────────────────time─┐
│ A    │     5 │ 2022-05-23 01:01:12 │
│ A    │     5 │ 2022-05-23 01:01:12 │
│ A    │     5 │ 2022-05-23 01:01:12 │
│ A    │     5 │ 2022-05-23 01:01:12 │
│ A    │     9 │ 2022-05-23 01:02:11 │
│ A    │     7 │ 2022-05-23 01:03:21 │
│ B    │     5 │ 2022-05-23 01:04:23 │
│ B    │     6 │ 2022-05-23 01:05:33 │
│ C    │     7 │ 2022-05-23 01:06:30 │
│ C    │     8 │ 2022-05-23 01:07:41 │
│ C    │     3 │ 2022-05-23 01:08:44 │
│ C    │     7 │ 2022-05-23 01:09:50 │
└──────┴───────┴─────────────────────┘

12 rows in set. Elapsed: 0.002 sec.

由于您需要整行(而 argMin/argMax 需要一个参数),因此需要将其转换为另一个结构(本例中为元组),然后投影回它们的名称。以下查询 returns 第一个(或参数为 val 表达式的最小值):

SELECT 
    tpl.1 AS name, 
    tpl.2 AS value, 
    tpl.3 AS time
FROM (
    SELECT 
        argMin(tuple(*), time) as tpl
    FROM 
        table1 
    GROUP BY name
)
ORDER BY name


┌─name─┬─value─┬────────────────time─┐
│ A    │     5 │ 2022-05-23 01:01:12 │
│ B    │     5 │ 2022-05-23 01:04:23 │
│ C    │     7 │ 2022-05-23 01:06:30 │
└──────┴───────┴─────────────────────┘


3 rows in set. Elapsed: 0.004 sec. 

由于 argMax 以类似的方式工作,但要获取最新的(或 val 表达式的最大值的参数),这将为您提供最新的(最新的)name/value/time 行:

SELECT
    tpl.1 AS name,
    tpl.2 AS value,
    tpl.3 AS time
FROM
(
    SELECT argMax(tuple(*), time) AS tpl
    FROM table1
    GROUP BY name
)
ORDER BY name ASC


┌─name─┬─value─┬────────────────time─┐
│ A    │     7 │ 2022-05-23 01:03:21 │
│ B    │     6 │ 2022-05-23 01:05:33 │
│ C    │     7 │ 2022-05-23 01:09:50 │
└──────┴───────┴─────────────────────┘

3 rows in set. Elapsed: 0.002 sec.