根据奇数和偶数将2列分成4列

Divide 2 columns into 4 based on odd and even

我想把2列按照奇数和偶数分成4列。我有一个 table

INSERT INTO @tab
VALUES ('test', 'desc'), ('test1', 'desc1'), ('test2', 'desc2'),
       ('test3', 'desc3'), ('test4', 'desc4')

我尝试了以下查询:-

SELECT  
    CASE 
       WHEN A.RNK  % 2 = 1 
          THEN Heading 
    END AS Headingodds,
    CASE 
       WHEN A.RNK  % 2 = 0 
          THEN Heading
    END AS Headingeven,
    CASE 
       WHEN A.RNK  % 2 = 1 
          THEN A.[Description] 
    END AS Descriptionodds, 
    CASE
       WHEN A.RNK  % 2 = 0 
          THEN A.[Description]
    END AS Descriptioneven
FROM
    (SELECT 
         Id, Heading, [Description],
         ROW_NUMBER() OVER (ORDER BY Id) AS RNK
     FROM
         @tab) A

我从查询中得到的结果是:-

但我想要以下格式的结果:-

DECLARE @tab1 TABLE(Headingodd VARCHAR(100), Headingeven VARCHAR(100), Descriptionodd VARCHAR(100), Descriptioneven VARCHAR(100))

INSERT INTO @tab1 
VALUES ('test', 'test1', 'desc', 'desc1'),
       ('test2', 'test3', 'desc2', 'desc3'),
       ('test4', null, 'desc4', null)

SELECT * FROM @tab1

您需要分别生成奇数和偶数标题和描述,然后您可以 JOIN 在匹配的行号上将它们一起

WITH A AS (
  SELECT Id, Heading, [Description],
         ROW_NUMBER() OVER (ORDER BY Id) AS RNK 
  FROM tab
),
ODD AS (
  SELECT Heading, [Description],
         (RNK - 1) / 2 AS RN
  FROM A 
  WHERE RNK % 2 = 1
),
EVEN AS (
  SELECT Heading, [Description],
         (RNK - 1) / 2 AS RN
  FROM A 
  WHERE RNK % 2 = 0
)
SELECT o.Heading AS Headingodds,
       e.Heading AS Headingeven,
       o.Description AS Descriptionodds,
       e.Description AS Descriptioneven
FROM ODD o
LEFT JOIN EVEN e ON e.RN = o.RN
ORDER BY o.RN

输出:

Headingodds     Headingeven     Descriptionodds     Descriptioneven
test            test1           desc                desc1
test2           test3           desc2               desc3
test4                           desc4   

Demo on dbfiddle

你也可以试试这个:

create table #tab(id int,test varchar(40),des varchar(40))

INSERT INTO #tab
VALUES (1,'test', 'desc'), (2,'test1', 'desc1'), (3,'test2', 'desc2'),
   (4,'test3', 'desc3'), (5,'test4', 'desc4')
select * from #tab

with cte as 
(select ROW_NUMBER()OVER(ORDER BY a.TestODD) row_num,* 
    from (select(case when id in (1,3,5)  then '0' else test end) TestODD from #tab) a  
    where a.TestODD!='0'),
cte2 as (
select ROW_NUMBER() OVER(ORDER BY b.TestEven)row_num,*
   from (select(case when id in(2,4)then '0' else test end)TestEven from #tab)b
   where b.TestEven!='0'
 ),
 cte3 as (
 select ROW_NUMBER()OVER(ORDER BY  c.desODD) row_num,* 
   from (select (case when id in (1,3,5)then '0' else des end) desODD from #tab)c  
   where c.desODD!='0'
 ),
 cte4 as (
 select ROW_NUMBER()OVER(ORDER BY d.destEven)row_num,* 
   from (select(case when id in (2,4)then '0' else des end)destEven from #tab) d  
   where d.destEven!='0'
 )
  select TestEven,TestODD,destEven,desODD from cte2
       left join cte on cte.row_num=cte2.row_num
      left join cte3 on cte2.row_num=cte3.row_num
      left join cte4 on cte2.row_num=cte4.row_num

其他答案看起来太复杂了。这实际上只是聚合和算术:

select min(case when rnk % 2 = 1 then heading end) as heading_odd,
       min(case when rnk % 2 = 0 then heading end) as heading_even,
       min(case when rnk % 2 = 1 then description end) as description_odd,
       min(case when rnk % 2 = 0 then description end) as description_even
from (select t.*, row_number() over (order by id) as rnk
      from tab t
     ) t
group by (rnk - 1) / 2
order by min(rnk);

Here 是一个 db<>fiddle.

注意:如果您知道 id 是连续的且没有间隙,您甚至不需要 rnk