数千列的动态枢轴
Posted
技术标签:
【中文标题】数千列的动态枢轴【英文标题】:Dynamic pivot for thousands of columns 【发布时间】:2015-07-16 14:13:35 【问题描述】:我正在使用 pgAdmin III / PostgreSQL 9.4 来存储和处理我的数据。我当前数据的样本:
x | y
--+--
0 | 1
1 | 1
2 | 1
5 | 2
5 | 2
2 | 2
4 | 3
6 | 3
2 | 3
我希望如何格式化:
1, 2, 3
-- 列名是唯一的 y
值0, 5, 4
-- 第一个对应的x
值1, 5, 6
-- 第二个对应的x
值@ 987654330@ -- 等等
它需要是动态的,因为我有数百万行和数千个 y
的唯一值。
为此使用动态枢轴方法是否正确?我无法成功地实现这一点:
DECLARE @columns VARCHAR(8000)
SELECT @columns = COALESCE(@columns + ',[' + cast(y as varchar) + ']',
'[' + cast(y as varchar)+ ']')
FROM tableName
GROUP BY y
DECLARE @query VARCHAR(8000)
SET @query = '
SELECT x
FROM tableName
PIVOT
(
MAX(x)
FOR [y]
IN (' + @columns + ')
)
AS p'
EXECUTE(@query)
它在第一行停止并给出错误:
syntax error at or near "@"
我见过的所有动态枢轴示例都使用这个,所以我不确定我做错了什么。任何帮助表示赞赏。感谢您的宝贵时间。
**注意:以正确的顺序存储x
值很重要,因为顺序很重要。如有必要,我可以添加另一列来指示顺序。
【问题讨论】:
首先,您是否尝试打印您的@query
?您可能会在那里找到有用的东西并对其进行调试。
嗨,Evaldas,我在尝试打印 @query 时遇到同样的错误:“@”或附近的语法错误
问题是代码是为 Microsoft SQL Server 编写的,并且是为 Microsoft SQL Server 编写的,因此在 Postgresql 中不起作用。不过,在 Postgresql 中也有一些方法可以做到这一点,例如这个问题所示:***.com/questions/28087948/…
也看到这个问题 - 它有更好的答案:***.com/questions/3002499/…
哦,谢谢。我对 SQL 很陌生,我尝试的来源没有指定使用的 SQL 类型。我将从另一篇文章开始工作,看看我能做什么。
【参考方案1】:
术语“第一行”假定行的自然顺序,这在数据库表中不存在。所以,是的,你需要像你怀疑的那样add another column to indicate sequential order
。为此,我假设有一列 tbl_id
。使用ctid
将是最后的手段。见:
您提供的代码看起来像 MS SQL Server 代码; Postgres 的语法无效。
对于millions of rows and thousands of unique values for Y
,尝试返回单个列甚至没有意义。 Postgres 有很大的限制,但还不够慷慨。 According to the source code 或the manual,绝对最大列数为1600。
所以我们甚至没有讨论 SQL 的限制性特征,它要求在执行时知道列和数据类型,而不是在执行期间动态调整。您将需要两个单独的调用,就像我们在此相关问题下详细讨论的那样。
Dynamic alternative to pivot with CASE and GROUP BYClodoaldo 在同一问题下的另一个答案返回数组。这实际上可以是完全动态的。这也是我在这里的建议。查询其实很简单:
WITH cte AS (
SELECT *, row_number() OVER (PARTITION BY y ORDER BY tbl_id) AS rn
FROM tbl
ORDER BY y, tbl_id
)
SELECT text 'y' AS col, array_agg (y) AS values
FROM cte
WHERE rn = 1
UNION ALL
( -- parentheses required
SELECT text 'x' || rn, array_agg (x)
FROM cte
GROUP BY rn
ORDER BY rn
);
结果:
col | values
----+--------
y | 1,2,3
x1 | 0,5,4
x2 | 1,5,6
x3 | 2,2,2
db小提琴here旧sqlfiddle
说明
CTE 为每组y
的每一行(每个x
)计算一个row_number rn
。我们将使用它两次,因此是 CTE。
外部查询中的第一个SELECT
生成y
值的数组。
外部查询中的第二个SELECT
按顺序生成所有x
值的数组。数组可以有不同的长度。
为什么UNION ALL
有括号?见:
【讨论】:
以上是关于数千列的动态枢轴的主要内容,如果未能解决你的问题,请参考以下文章