将行拆分为 12 列
Posted
技术标签:
【中文标题】将行拆分为 12 列【英文标题】:Split rows into 12 columns 【发布时间】:2012-10-15 06:38:40 【问题描述】:我有一个表,比如说,1000 行。其中一列是 URL。
所以,从表格中选择 URL。
但是我想每行显示 12 个 URL。原因是我们正在发布供人们在线完成的工作,他们将一次审查 12 个网站。
因此,在这种情况下,我们将输出大约 90 行,每行有 12 列(除了最后一行会短一些)。
有没有一种简单的方法可以做到这一点?这是枢轴或其他功能的情况吗?
【问题讨论】:
从行中提取 12 个 URls 是否有任何标准? 您可以使用 LIMIT 进行分页,但真正的解决方案不是在 SQL 查询中执行此操作,而是在您的软件的表示层中执行此操作。 您使用的是什么关系型数据库? SQL Server、mysql、oracle? 【参考方案1】:动态 PIVOT 的简单示例
CREATE TABLE dbo.Url
(
Id int IDENTITY,
url nvarchar(max)
)
INSERT dbo.Url
VALUES ('http://www.url1.com'),
('http://www.url2.com'),
('http://www.url3.com'),
('http://www.url4.com')
DECLARE @cols AS nvarchar(MAX),
@query AS nvarchar(MAX)
SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(ROW_NUMBER() OVER (ORDER BY Url))
FROM dbo.url
GROUP BY Url
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET @query = 'SELECT' + @cols + ' FROM
(
SELECT Id, url
FROM dbo.url
) x
PIVOT
(
MAX(url)
FOR Id IN (' + @cols + ')
) p '
EXECUTE(@query)
【讨论】:
谢谢 Alexander,但我得到:Msg 1056, Level 15, State 1, Line 1 选择列表中的元素数量超过了 4096 个元素的最大允许数量。消息 102,级别 15,状态 1,第 5 行 'x' 附近的语法不正确。 您需要阅读这些帖子:如何接受答案? meta.stackexchange.com/questions/5234/…【参考方案2】:这是在线解决方案。不过可能看起来有点复杂
declare @Temp_URLS table (URL nvarchar(128))
declare @Temp_Reviewers table (Name nvarchar(128))
insert into @Temp_Reviewers (Name)
select top 5
'Reviewer' +
right('0000' +
cast(row_number() over (order by number) as nvarchar(128)), 4)
from master.dbo.spt_values
insert into @Temp_URLS (URL)
select top 30
'http://URL' +
right('0000' +
cast(row_number() over (order by number) as nvarchar(128)), 4) + '.com'
from master.dbo.spt_values
select
Name,
[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]
from
(
select TT.Name, row_number() over (order by TT.Name asc) as RowNum
from @Temp_Reviewers as TT
) as R
outer apply
(
select top 12 TT.URL, row_number() over (order by TT.URL) as RowNum
from
(
select TTT.URL, 1 + row_number() over (order by TTT.URL asc) / 12 as RowNum
from @Temp_URLS as TTT
) as TT
where TT.RowNum = R.RowNum
) as CALC
pivot
(
min(CALC.URL)
for CALC.RowNum in
([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) as PVT
这是没有 Pivot 和 Row_Number 的解决方案
declare @Temp_URLS table (URL nvarchar(128), csikey int identity(1, 1))
insert into @Temp_URLS (URL)
select top 30
'http://URL' +
right('0000' +
cast(row_number() over (order by number) as nvarchar(128)), 4) + '.com'
from master.dbo.spt_values
select
A.RowNum1,
min(case when A.RowNum2 = 1 then A.URL else null end) as [1],
min(case when A.RowNum2 = 2 then A.URL else null end) as [2],
min(case when A.RowNum2 = 3 then A.URL else null end) as [3],
min(case when A.RowNum2 = 4 then A.URL else null end) as [4],
min(case when A.RowNum2 = 5 then A.URL else null end) as [5],
min(case when A.RowNum2 = 6 then A.URL else null end) as [6],
min(case when A.RowNum2 = 7 then A.URL else null end) as [7],
min(case when A.RowNum2 = 8 then A.URL else null end) as [8],
min(case when A.RowNum2 = 9 then A.URL else null end) as [9],
min(case when A.RowNum2 = 10 then A.URL else null end) as [10],
min(case when A.RowNum2 = 11 then A.URL else null end) as [11],
min(case when A.RowNum2 = 12 then A.URL else null end) as [12]
from
(
select
T1.csikey, T1.URL,
count(T2.csikey) / 12 + 1 as RowNum1,
count(T2.csikey) % 12 + 1 as RowNum2
from @Temp_URLS as T1
left outer join @Temp_URLS as T2 on T2.csikey < T1.csikey
group by T1.csikey, T1.URL
) as A
group by A.RowNum1
【讨论】:
只是一个简短的注释 Roman。实际上,我们将所有必要的数据存储在一张表中。它具有列 a (csikey) 和列 b (url),这是一个唯一 ID,但不是数字。上面的这个查询可以很容易地修改为只引用一个表吗?为了您的帮助,我也很乐意通过 paypal 给您几块钱:) 我添加了一个没有 rownumber 和 pivot 的解决方案。不幸的是,我对 Oracle 没有太多经验【参考方案3】:请尝试以下查询,它适用于 Oracle 11G:
SELECT * FROM(
SELECT URL,
CAST(FLOOR((NUM+2)/3) AS INT) AS Row_Num,
MOD(NUM+2, 3)+1 AS OrderNum
FROM(
SELECT
ROW_NUMBER() OVER (ORDER BY URL) as NUM, URL
FROM
TBL_URL
)T1
)T2 PIVOT (MIN(URL) FOR OrderNum IN ('1' AS "1", '2' AS "2", '3' AS "3"));
【讨论】:
以上是关于将行拆分为 12 列的主要内容,如果未能解决你的问题,请参考以下文章