Sql 为两个字段创建两个数组,保持数组的排序顺序同步(无子查询)
这个问题没有任何押韵或理由,我只是好奇人们会怎么做 平台:当我希望有一个SQL标准解决方案时,我的主要精力集中在PostgreSQL 8.4+。(我知道9.0+有一些数组排序功能。) 我知道下面的查询是错误的,但结果与我想要的结果相似;将两个字段联系起来的方法(对Sql 为两个字段创建两个数组,保持数组的排序顺序同步(无子查询),sql,arrays,postgresql,sorting,aggregate-functions,Sql,Arrays,Postgresql,Sorting,Aggregate Functions,这个问题没有任何押韵或理由,我只是好奇人们会怎么做 平台:当我希望有一个SQL标准解决方案时,我的主要精力集中在PostgreSQL 8.4+。(我知道9.0+有一些数组排序功能。) 我知道下面的查询是错误的,但结果与我想要的结果相似;将两个字段联系起来的方法(对组的排序也应该对dt进行排序): 是否有一种简单的方法来绑定字段进行排序,而不使用子查询?也许构建一个数组,然后取消它?我所知道的唯一使其平坦化的方法是使用一个数组。以下是查询的外观: --We first need to create
组的排序也应该对dt
进行排序):
是否有一种简单的方法来绑定字段进行排序,而不使用子查询?也许构建一个数组,然后取消它?我所知道的唯一使其平坦化的方法是使用一个数组。以下是查询的外观:
--We first need to create the order hierarchy to recurse properly
SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY group) AS rownum
INTO TEMP TableToRecurse
FROM foo
WITH RECURSIVE FinalOutput (id, group, dt, rownum) AS
(
--Anchor row of recursion
SELECT id, group, dt, rownum
FROM TableToRecurse
WHERE rownum = 1
UNION ALL
--Recursion piece
SELECT tr.id, FinalOutput.group || ', ' || tr.group,
FinalOutput.dt || ', ' || tr.dt, tr.rownum
FROM TableToRecurse AS tr
JOIN FinalOutput
ON FinalOutput.id = tr.id AND FinalOutput.rownum = tr.rownum +1
)
--Final output only showing the last row (Max)
--Which should have everything concatenated together
SELECT FinalOutput.id, FinalOutput.group, FinalOutput.dt
FROM FinalOutput
JOIN
(
SELECT MAX(rownum) AS MaxRowNum, id
FROM FinalOutput
GROUP BY id
) AS MaxForEach
ON FinalOutput.id = MaxForEach.id
AND FinalOutput.rownum = MaxForEach.MaxRowNum
我所知道的唯一能让它变得平坦的方法就是使用。以下是查询的外观:
--We first need to create the order hierarchy to recurse properly
SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY group) AS rownum
INTO TEMP TableToRecurse
FROM foo
WITH RECURSIVE FinalOutput (id, group, dt, rownum) AS
(
--Anchor row of recursion
SELECT id, group, dt, rownum
FROM TableToRecurse
WHERE rownum = 1
UNION ALL
--Recursion piece
SELECT tr.id, FinalOutput.group || ', ' || tr.group,
FinalOutput.dt || ', ' || tr.dt, tr.rownum
FROM TableToRecurse AS tr
JOIN FinalOutput
ON FinalOutput.id = tr.id AND FinalOutput.rownum = tr.rownum +1
)
--Final output only showing the last row (Max)
--Which should have everything concatenated together
SELECT FinalOutput.id, FinalOutput.group, FinalOutput.dt
FROM FinalOutput
JOIN
(
SELECT MAX(rownum) AS MaxRowNum, id
FROM FinalOutput
GROUP BY id
) AS MaxForEach
ON FinalOutput.id = MaxForEach.id
AND FinalOutput.rownum = MaxForEach.MaxRowNum
试试这个:
select id,
array_agg(agroup order by agroup) as AGroup,
array_agg(dt order by dt desc) as dt
from t
group by id
这应该适用于PostgreSQL 9.1+尝试以下方法:
select id,
array_agg(agroup order by agroup) as AGroup,
array_agg(dt order by dt desc) as dt
from t
group by id
这应该适用于PostgreSQL 9.1+我将您的列名group
更改为grp
,因为group
在Postgres和每个SQL标准中都是一个名称,不应该用作标识符
我理解你的问题是这样的:
以相同的排序顺序对两个数组进行排序,以便相同的元素位置对应于两个数组中的同一行
使用子查询或CTE并在聚合前对行排序
SELECT id, array_agg(grp) AS grp, array_agg(dt) AS dt
FROM (
SELECT *
FROM tbl
ORDER BY id, grp, dt
) x
GROUP BY id;
这比使用单独的array\u agg()
like(自PostgreSQL 9.0以来一直存在)更快。Mosty对你的问题也有不同的解释,并使用适当的工具进行解释
子查询中的排序依据是否安全?
聚合函数array\u agg
,json\u agg
,[…]以及
类似的用户定义聚合函数,产生有意义的
不同的结果值取决于输入值的顺序。
默认情况下,此顺序未指定,但可以由控制
在聚合调用中编写一个orderby
子句,如中所示
部分或者,从
排序的子查询通常会工作。例如:
SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
请注意,如果外部查询级别包含
附加处理,例如联接,因为这可能导致
要在计算聚合之前对子查询的输出进行重新排序
是的,在这个例子中是安全的
无子查询
如果确实需要不带子查询的解决方案,可以:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
请注意按grp、dt排序的。除了断开连接并使排序顺序明确之外,我还按dt
进行排序。不过,grp
不需要
还有一种完全不同的方法可以做到这一点:
请注意(id)
上的DISTINCT,而不仅仅是DISTINCT
,它产生相同的结果,但执行速度要快一个数量级,因为我们不需要额外的排序
我运行了一些测试,这几乎和其他两个解决方案一样快。正如所料,子查询版本仍然是最快的。使用EXPLAIN analysis
进行测试,亲自查看。我将您的列名group
更改为grp
,因为group
是Postgres和每个SQL标准中的一个名称,不应用作标识符
我理解你的问题是这样的:
以相同的排序顺序对两个数组进行排序,以便相同的元素位置对应于两个数组中的同一行
使用子查询或CTE并在聚合前对行排序
SELECT id, array_agg(grp) AS grp, array_agg(dt) AS dt
FROM (
SELECT *
FROM tbl
ORDER BY id, grp, dt
) x
GROUP BY id;
这比使用单独的array\u agg()
like(自PostgreSQL 9.0以来一直存在)更快。Mosty对你的问题也有不同的解释,并使用适当的工具进行解释
子查询中的排序依据是否安全?
聚合函数array\u agg
,json\u agg
,[…]以及
类似的用户定义聚合函数,产生有意义的
不同的结果值取决于输入值的顺序。
默认情况下,此顺序未指定,但可以由控制
在聚合调用中编写一个orderby
子句,如中所示
部分或者,从
排序的子查询通常会工作。例如:
SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
请注意,如果外部查询级别包含
附加处理,例如联接,因为这可能导致
要在计算聚合之前对子查询的输出进行重新排序
是的,在这个例子中是安全的
无子查询
如果确实需要不带子查询的解决方案,可以:
SELECT id
, array_agg(grp ORDER BY grp)
, array_agg(dt ORDER BY grp, dt)
FROM tbl
GROUP BY id;
请注意按grp、dt排序的。除了断开连接并使排序顺序明确之外,我还按dt
进行排序。不过,grp
不需要
还有一种完全不同的方法可以做到这一点:
请注意(id)
上的DISTINCT,而不仅仅是DISTINCT
,它产生相同的结果,但执行速度要快一个数量级,因为我们不需要额外的排序
我运行了一些测试,这几乎和其他两个解决方案一样快。正如所料,子查询版本仍然是最快的。使用EXPLAIN ANALYZE
进行测试,亲自查看。非常有趣-我必须更详细地了解这一点。这不是有效的PostgreSQL语法。看起来它是针对SQL Server的?是的,我的背景是SQL Server,但我仔细检查了这是否可以在PostGreSQL中完成(请参阅我的链接)。我注意到临时表语法不同,但我认为现在应该修复它。否则,这有什么问题吗?是的,我看到有哈希标记时不是Postgres,但我认为两个数据库之间的递归结构是相同的。@JustinPihony: