INSERT INTO "public"."catalog_element"
("id", "catalogue_id", "element_id", "weight") VALUES
(1,100,1,0),
(2,100,2,1),
(3,100,3,2),
(4,10,1,0),
(5,10,5,0),
(6,10,6,1),
(7,100,7,1);
假设我们有一个包含catalog *- to -* element
匹配行的Postgres表,这些行是加权的,如下所示
| 身份证|目录标识|元素标识|重量|
| - ------|- ------|- ------|- ------|
| 1个|一百|1个|无|
| 第二章|一百|第二章|1个|
| 三个|一百|三个|第二章|
| 四个|十个|1个|无|
| 五个|十个|五个|无|
| 六个|十个|六个|1个|
| 七|一百|七|1个|
我尝试编写一个查询,返回绑定到特定catalog_id
的记录,按权重排序,范围从第一个到具有特定element_id
的一个。
例如,catalog_id = 100
按权重对DESC
排序,并且每隔一行,直到element_id = 7
满足,最终得到以下结果:
| 身份证|目录标识|元素标识|重量|
| - ------|- ------|- ------|- ------|
| 三个|一百|三个|第二章|
| 第二章|一百|第二章|1个|
| 七|一百|七|1个|
5条答案
按热度按时间wlp8pajw1#
您可以使用子查询获取所需的权重,然后选择大于该权重的列
| 身份证|目录标识|元素标识|重量|
| - ------|- ------|- ------|- ------|
| 第二章|一百|第二章|1个|
| 三个|一百|三个|第二章|
| 七|一百|七|1个|
fiddle
5ktev3wc2#
我不确定你是否认为我的解决方案不那么笨拙,它确实避免了自连接,这应该会为大型表带来更好的性能。
收益率
| 低频磁场|最大_标志|旗|身份证|目录标识|元素标识|重量|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 无|无|无|三个|一百|三个|第二章|
| 无|无|无|第二章|一百|第二章|1个|
| 无|1个|1个|七|一百|七|1个|
使用以下设置
虽然这样的声明看起来很吓人,但实际上并不难理解。
1.您使用的是analytic or windowing functions yourself, so I assume basic knowledge of their working。
1.因为你不能直接嵌套这样的函数,所以我使用嵌套的选择,每一层嵌套添加一个函数,因此这样的语句应该从里到外读取。
1.* with_flag * 的最里面一个
wf
使用以下命令添加一个flag
列标记被截断的行。这发生在它自己的子选择中,因为我们在下一步中需要两次标记。
1.在
wmf
for * with_max_flag * 中,我们使用max(flag) over( order by weight desc, flag)
来创建max_flag
列,该列对于截止行之前的所有行都具有0
。这并不是说我们也按flag
排序,以便对于与截止行具有相同权重的那些行也具有0
。1.现在我们几乎可以按行过滤了,但是我们希望包含从row中删除的行,所以我们使用
lag
将max_flag
移动一行,并使用coalesce
将null
的值转换为0
,对于 * with_lag_max_flag *,这在wlmf
中发生。1.最后,我们只过滤掉需要的行。
生成的SQL语句看起来很笨拙,但它只访问数据一次,并且始终按照相同的标准排序。我对类似的、实际上更大的语句的经验是,它们执行得非常好。
View on DB Fiddle
ovfsdjhp3#
使用LATERAL计算最大相关权重。取权重较大的所有行,仅取到element_id = 7为止具有该权重的行。对于element_id = 7,可能返回多行。定义额外的标准以选择单个element_id = 7行。
55ooxyrt4#
要在给定insert语句中的数据上选择最多为某个ID的有序行,可以使用以下SQL查询:
替换<max_id>为要包含在结果中的最大ID值。此查询将从catalog_element表中选择ID值小于或等于指定的最大ID的所有行,并首先按catalog_id升序、然后按weight升序、最后按element_id升序对结果进行排序。
例如,如果要选择ID值小于或等于5的所有行,则查询应为:
这将返回以下行:
kcwpcxri5#
我找到了做我想做的事的方法,但是太笨拙了