我有一个查询返回2列:
Product | Price
------------------
Product01 | 10.00
Product02 | 10.00
Product03 | 10.00
Product04 | 10.00
Product05 | 10.00
Product06 | 10.00
Product07 | 10.00
Product08 | 10.00
Product09 | 10.00
Product10 | 10.00
我想做的就是以这种形式返回相同的数据:
Product1 | Price1 | Product2 | Price2 | Product3 | Price3
---------------------------------------------------------------
Product01 | 10.00 | Product05 | 10.00 | Product08 | 10.00
Product02 | 10.00 | Product06 | 10.00 | Product09 | 10.00
Product03 | 10.00 | Product07 | 10.00 | Product10 | 10.00
Product04 | 10.00 | NULL | NULL | NULL | NULL
到目前为止,这是我的代码:
DECLARE @COLUMNS INT
SET @COLUMNS = 3
;
WITH CTE AS (
SELECT
ROW_NUMBER() OVER ( PARTITION BY [COLUMN] ORDER BY ROW ASC ) AS ID_IN_GROUP
,*
FROM (
SELECT
ROW_NUMBER() OVER ( ORDER BY Name ASC ) AS ROW
,NTILE(@COLUMNS) OVER ( ORDER BY Name ASC ) AS [COLUMN]
,*
FROM
Products
) X
)
SELECT A.Name as Product1, A.Price as Price1, B.Name as Product2, B.Price as Price2, C.Name as Product3, C.Price as Price3 FROM
(SELECT Name,Price,ID_IN_GROUP FROM CTE WHERE [COLUMN]=1) A
CROSS APPLY
(SELECT Name,Price, ID_IN_GROUP FROM CTE WHERE [COLUMN]=2) B
CROSS APPLY
(SELECT Name,Price, ID_IN_GROUP FROM CTE WHERE [COLUMN]=3) C
WHERE
B.ID_IN_GROUP=A.ID_IN_GROUP
AND C.ID_IN_GROUP=A.ID_IN_GROUP
http://sqlfiddle.com/#!18/bf3b4/30
它返回几乎想要的结果:
Product1 | Price1 | Product2 | Price2 | Product3 | Price3
---------------------------------------------------------------
Product01 | 10.00 | Product05 | 10.00 | Product08 | 10.00
Product02 | 10.00 | Product06 | 10.00 | Product09 | 10.00
Product03 | 10.00 | Product07 | 10.00 | Product10 | 10.00
但缺少最后一行-Product04。如何解决?
编辑:我已通过将CROSS APPLY更改为LEFT JOIN来解决此问题,
DECLARE @COLUMNS INT
SET
@COLUMNS = 3;
WITH CTE AS (
SELECT
ROW_NUMBER() OVER (
PARTITION BY [COLUMN]
ORDER BY
ROW ASC
) AS ID_IN_GROUP,
*
FROM
(
SELECT
ROW_NUMBER() OVER (
ORDER BY
Name ASC
) AS ROW,
NTILE(@COLUMNS) OVER (
ORDER BY
Name ASC
) AS [COLUMN],
*
FROM
Products
) X
)
SELECT
A.Name as Product1,
A.Price as Price1,
B.Name as Product2,
B.Price as Price2,
C.Name as Product3,
C.Price as Price3
FROM
(
SELECT
Name,
Price,
ID_IN_GROUP
FROM
CTE
WHERE
[COLUMN] = 1
) A
LEFT JOIN (
SELECT
Name,
Price,
ID_IN_GROUP
FROM
CTE
WHERE
[COLUMN] = 2
) B ON B.ID_IN_GROUP = A.ID_IN_GROUP
LEFT JOIN (
SELECT
Name,
Price,
ID_IN_GROUP
FROM
CTE
WHERE
[COLUMN] = 3
) C ON C.ID_IN_GROUP = A.ID_IN_GROUP
http://sqlfiddle.com/#!18/bf3b4/61
这有可能使它更具动态性吗?因此,当我将@COLUMNS更改为4时,它将返回4组吗?
答案 0 :(得分:1)
您要的东西比我想的要难。我还没有弄清楚逻辑,但这很接近:
SELECT MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 0 THEN Name END) as Product1,
MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 0 THEN Price END) as Price1,
MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 1 THEN Name END) as Product2,
MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 1 THEN Price END) as Price2,
MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 2 THEN Name END) as Product3,
MAX(CASE WHEN floor((seqnum - 1) / ceiling(cnt / 3.0)) = 2 THEN Price END) as Price3
FROM (SELECT p.*,
ROW_NUMBER() OVER (ORDER BY Name) as seqnum,
COUNT(*) OVER () as cnt
FROM Products p
) p
GROUP BY (seqnum - 1) % ceiling(cnt / 3.0);
区别在于,这会“贪婪地”填充列,因此列是4-4-2而不是4-3-3。这种方法的一个优点是,如果添加第11行,则各列保持不变。