假设我有一个像这样的透视排序数据集
ID Col1 Col2 1 a 11 2 b 22 3 c 33 4 d 44 5 e 55
当我通过一次返回两条记录进行分页调用时,我会得到前两行。
假设我想返回相同的数据但不转动数据,因此我的数据集看起来像
ID Col Val 1 Col1 a 2 Col1 b 3 Col1 c 4 Col1 d 5 Col1 e 1 Col2 11 2 Col2 22 3 Col2 33 4 Col2 44 5 Col2 55
我想编写一个sql语句,该语句将返回与第一个示例中相同的数据但不首先转动数据。
一些额外的挑战
1)可能有n列不仅仅是两个
2)Tt还应支持所有列的过滤器。这部分我已经解决了,见下文
Filter on pivoted data WHERE Col1 in ('a', 'b', 'c') AND Col2 in ('11', '22') Filter on unpivoted data WHERE (Col = 'Col1' and Val in ('a', 'b', 'c')) or Col != 'Col1') AND (Col = 'Col2' and Val in ('11', '22')) or Col != 'Col2') Both filters return the same results.
我已经想到的过滤器部分已经停留在排序和分页上了。
答案 0 :(得分:1)
SQL作为标准,不支持此类操作。如果您希望它处理任意多列以重新格式化数据,那么请使用Perl的DBI接口,它可以告诉您任何表的列名称。从那里你可以生成你的表格。
要创建第二个表格,插入内容将采用以下形式:
INSERT INTO newtable (id, col, val)
SELECT id, 'Col1', Col1 from oldtable
UNION
SELECT id, 'Col2', Col2 from oldtable;
只需为要包含的每列创建一个额外的UNION SELECT...
。
至于你过滤查询,你会让它变得不必要地复杂化。您的查询:
SELECT * FROM newtable
WHERE (Col = 'Col1' and Val in ('a', 'b', 'c')) or Col != 'Col1')
AND (Col = 'Col2' and Val in ('11', '22')) or Col != 'Col2')
可以改写为
SELECT * from newtable
WHERE ( Col = 'Col1' and Val in ('a','b','c') )
OR ( Col = 'Col2' and Val in ('11','22') )
每个单独的OR
d条款不会干扰其他条款。
我也不明白为什么人们试图在SQL中运行这样的travesties。您似乎正在尝试将合理的架构设置为类似于键/值存储的东西。现在,这对孩子们来说可能风靡一时,但你应该真正学会如何利用SQL的全部功能和良好的数据建模。