标签: greatest-n-per-group

每组检索 n 行

我经常需要从结果集中的每个组中选择一些行。

例如,我可能想列出每个客户最近的“n”个最高或最低订单值。

在更复杂的情况下,要列出的行数可能因组而异(由分组/父记录的属性定义)。这部分绝对是可选的/为了额外的学分,而不是为了劝阻人们回答。

在 SQL Server 2005 及更高版本中解决这些类型问题的主要选项是什么?每种方法的主要优点和缺点是什么?

AdventureWorks 示例(为清晰起见,可选)

  1. 列出表中五个最近的交易日期和 ID TransactionHistory,每个产品以从 M 到 R 的字母开头。
  2. 再次相同,但n每个产品都有历史记录行,其中nDaysToManufactureProduct 属性的五倍。
  3. 同样,对于每个产品恰好需要一条历史记录行的特殊情况(最近的单个条目由TransactionDate, .tie-break on TransactionID.

sql-server t-sql greatest-n-per-group

97
推荐指数
6
解决办法
7万
查看次数

如何有效地获得“最近的对应行”?

我有一个一定很常见的查询模式,但我不知道如何为它编写有效的查询。我想查找与“最近日期不晚于”另一个表的行相对应的表的行。

inventory比如说,我有一张表格,它代表了我在某一天持有的库存。

date       | good | quantity
------------------------------
2013-08-09 | egg  | 5
2013-08-09 | pear | 7
2013-08-02 | egg  | 1
2013-08-02 | pear | 2
Run Code Online (Sandbox Code Playgroud)

和一张表,“价格”说,它保存了某一天的商品价格

date       | good | price
--------------------------
2013-08-07 | egg  | 120
2013-08-06 | pear | 200
2013-08-01 | egg  | 110
2013-07-30 | pear | 220
Run Code Online (Sandbox Code Playgroud)

如何有效地获得库存表每一行的“最新”价格,即

date       | pricing date | good | quantity | price
----------------------------------------------------
2013-08-09 | 2013-08-07   | egg  | 5        | 120
2013-08-09 …
Run Code Online (Sandbox Code Playgroud)

postgresql performance greatest-n-per-group query-performance

68
推荐指数
5
解决办法
13万
查看次数

如何选择每组的第一行?

我有一张这样的表:

 ID |  Val   |  Kind
----------------------
 1  |  1337  |   2
 2  |  1337  |   1
 3  |   3    |   4
 4  |   3    |   4
Run Code Online (Sandbox Code Playgroud)

我想制作一个SELECT只返回每个 的第一行,按Val排序Kind

示例输出:

 ID |  Val   |  Kind
----------------------
 2  |  1337  |   1
 3  |   3    |   4
Run Code Online (Sandbox Code Playgroud)

如何构建此查询?

oracle greatest-n-per-group

67
推荐指数
4
解决办法
39万
查看次数

在 PostgreSQL 中,是否有类型安全的 first() 聚合函数?

完整问题重写

我正在寻找 First() 聚合函数。

在这里,我发现了一些几乎有效的东西:

CREATE OR REPLACE FUNCTION public.first_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$
        SELECT $1;
$$;

-- And then wrap an aggregate around it
CREATE AGGREGATE public.first (
        sfunc    = public.first_agg,
        basetype = anyelement,
        stype    = anyelement
);
Run Code Online (Sandbox Code Playgroud)

问题是当 varchar(n) 列通过 first() 函数时,它会被转换为简单的 varchar(没有大小)。尝试在函数中将查询返回为 RETURNS SETOF anyelement,我收到以下错误:

错误:查询的结构与函数结果类型 Estado de SQL:42804 不匹配:返回的类型字符变化与第 2 列中的预期类型字符变化(40) 不匹配。上下文:PL/pgSQL 函数 vsr_table_at_time(anyelement,timestamp without time zone ) 第 31 行在 RETURN QUERY

在同一个 wiki 页面中,有一个指向该函数 …

postgresql aggregate functions greatest-n-per-group

25
推荐指数
3
解决办法
3万
查看次数

SQL Server - 当性能至关重要时从每个组中选择最近的记录

我运行了一个 SQL Server 2016 数据库,其中有一个包含 100 多万行的下表:

StationId | ParameterId |       DateTime       | Value
    1     |      2      | 2020-02-04 15:00:000 |  5.20
    1     |      2      | 2020-02-04 14:00:000 |  5.20
    1     |      2      | 2020-02-04 13:00:000 |  5.20
    1     |      3      | 2020-02-04 15:00:000 |  2.81
    1     |      3      | 2020-02-04 14:00:000 |  2.81
    1     |      4      | 2020-02-04 15:00:000 |  5.23
    2     |      2      | 2020-02-04 15:00:000 |  3.70
    2     |      4      | 2020-02-04 15:00:000 |  12.20
    3     | …
Run Code Online (Sandbox Code Playgroud)

index sql-server optimization greatest-n-per-group sql-server-2016

19
推荐指数
1
解决办法
3万
查看次数

选择哪个具有最大日期或最晚日期

这里有两张桌子。

学校员工

SCHOOL_CODE + STAFF_TYPE_NAME + LAST_UPDATE_DATE_TIME + PERSON_ID
=================================================================
ABE           Principal         24-JAN-13               111222
ABE           Principal         09-FEB-12               222111
Run Code Online (Sandbox Code Playgroud)

PERSON_ID + NAME
=================
111222      ABC
222111      XYZ
Run Code Online (Sandbox Code Playgroud)

这是我的 oracle 查询。

SELECT MAX(LAST_UPDATE_DATE_TIME) AS LAST_UPDATE, SCHOOL_CODE, PERSON_ID
FROM SCHOOL_STAFF
WHERE STAFF_TYPE_NAME='Principal'
GROUP BY SCHOOL_CODE, PERSON_ID
ORDER BY SCHOOL_CODE;
Run Code Online (Sandbox Code Playgroud)

这给出了这个结果

LAST_UPDATE SCHOOL_CODE PERSON_ID
===========+===========+=========
24-JAN-13   ABE         111222
09-FEB-12   ABE         222111
Run Code Online (Sandbox Code Playgroud)

我想为日期最晚的学校选择第一个。

谢谢。

oracle greatest-n-per-group

17
推荐指数
2
解决办法
53万
查看次数

从大表中获取每组最大价值的高效查询

鉴于表:

    Column    |            Type             
 id           | integer                     
 latitude     | numeric(9,6)                
 longitude    | numeric(9,6)                
 speed        | integer                     
 equipment_id | integer                     
 created_at   | timestamp without time zone
Indexes:
    "geoposition_records_pkey" PRIMARY KEY, btree (id)
Run Code Online (Sandbox Code Playgroud)

该表有 2000 万条记录,相对而言,这不是一个大数目。但它会使顺序扫描变慢。

我怎样才能获得max(created_at)每个的最后一条记录 ( ) equipment_id

我已经尝试了以下两个查询,其中有几个变体,我已经阅读了本主题的许多答案:

select max(created_at),equipment_id from geoposition_records group by equipment_id;

select distinct on (equipment_id) equipment_id,created_at 
  from geoposition_records order by equipment_id, created_at desc;
Run Code Online (Sandbox Code Playgroud)

我也尝试过创建 btree 索引,equipment_id,created_at但 Postgres 发现使用 seqscan 更快。强制enable_seqscan = off也没有用,因为读取索引与 seq 扫描一样慢,可能更糟。

查询必须定期运行,始终返回最后一个。

使用 Postgres …

postgresql performance index greatest-n-per-group

17
推荐指数
2
解决办法
3万
查看次数

获取表中第二高的值

id value
1   50
2   60
3   55

select max(value) from tablename;
Run Code Online (Sandbox Code Playgroud)

一般我们知道,我们会得到 60,但我需要下一个值 55。

如何使用 SQL 获取值 55?

sql-server greatest-n-per-group

16
推荐指数
5
解决办法
4万
查看次数

如何在 PostgreSQL 中使 DISTINCT ON 更快?

station_logs在 PostgreSQL 9.6 数据库中有一个表:

    Column     |            Type             |    
---------------+-----------------------------+
 id            | bigint                      | bigserial
 station_id    | integer                     | not null
 submitted_at  | timestamp without time zone | 
 level_sensor  | double precision            | 
Indexes:
    "station_logs_pkey" PRIMARY KEY, btree (id)
    "uniq_sid_sat" UNIQUE CONSTRAINT, btree (station_id, submitted_at)
Run Code Online (Sandbox Code Playgroud)

我试图level_sensor根据submitted_at, 对于每个station_id. 大约有 400 个唯一station_id值,每个station_id.

创建索引之前:

EXPLAIN ANALYZE
SELECT DISTINCT ON(station_id) station_id, submitted_at, level_sensor
FROM station_logs ORDER BY station_id, submitted_at DESC;
Run Code Online (Sandbox Code Playgroud)
 唯一(成本=4347852.14..4450301.72行=89宽度=20)(实际时间=22202.080..27619.167行=98循环=1)
   -> Sort …

postgresql performance greatest-n-per-group postgresql-9.6 query-performance

16
推荐指数
2
解决办法
1万
查看次数

如何从在主键上返回多行的连接中选择第一行

这与这个问题有关: Joining multiple tables results in duplicate rows

我有两个要加入的表。他们共用一个钥匙。person 表的每个主键有一个名称,而 email 表的每个 personId 有多个电子邮件。我只想显示每个人的第一封电子邮件。目前我每人收到多行,因为他们有多封电子邮件。我正在运行 SQL-Server 2005。

编辑:这是 T-SQL。第一封电子邮件实际上是每个人的第一封电子邮件行。

编辑 2:我看到的第一封电子邮件将是在 SQL 通过查询工作时显示在联接中的第一封电子邮件行。我不管出现哪个电子邮件。只是显示不超过一封电子邮件。我希望这能让它更清楚。

Table1: Person
Table2: Email

Select Person.PersonName, Email.Email
From person 
left join on Person.ID=Email.PersonId;
Run Code Online (Sandbox Code Playgroud)

sql-server-2005 sql-server greatest-n-per-group

15
推荐指数
4
解决办法
10万
查看次数