如何将表旋转45度并将结果保存到另一个表中?

时间:2011-02-26 11:23:52

标签: sql sql-server algorithm matrix

我有一张桌子。

---------
| a | b |
---------
| a | b |
---------

我想将其旋转45度(顺时针或逆时针)并将其保存到另一张桌子中。例如,如果我逆时针旋转45度,它将是:

-------------
| b |   |   |
-------------
| a | b |   |
-------------
| a |   |   |
-------------

另一个例子,当我旋转

-------------
| a | b | c |
-------------
| d | e | f |
-------------
| g | h | i |
-------------

它将变为

---------------------
| c |   |   |   |   |
---------------------
| b | f |   |   |   |
---------------------
| a | e | i |   |   |
---------------------
| d | h |   |   |   |
---------------------
| g |   |   |   |   |
---------------------

如何在SQL中执行此操作?

4 个答案:

答案 0 :(得分:65)

完整的工作示例(适用于SQL Server 2005+)
如果你需要它用于另一个系统,那么下面的拼图有等价物

  • ROW_NUMBER()
  • DENSE_RANK()
  • UN /枢轴

您可以从其他Stackoverflow问题中找到等效项。例如,Oracle和DB2很好地支持前两个。

create table t45 (id int identity, colA char(1), colX char(1), colZ char(1))
insert t45 select 'a','b','c'
insert t45 select 'd','e','f'
insert t45 select 'g','h','i'
GO

select [1],[2],[3],[4],[5] -- for N columns, this goes to N*2-1
from
(
    select value,
        targetRow = row+col-1,
        targetCol = ROW_NUMBER() over (partition by row+col-1 order by row)
    from
    (
        select *,
            row = DENSE_RANK() over (order by id),
            col = ROW_NUMBER() over (partition by id order by
                CASE source when 'colA' then 3 -- number in reverse
                            when 'colX' then 2
                            when 'colZ' then 1 end)
        from t45
        unpivot (value for source in (colA,colX,colZ)) upv
    ) x
) p                                -- for N columns, this goes to N*2-1
pivot (max(value) for targetCol in ([1],[2],[3],[4],[5])) pv
order by targetRow

如果您需要随意将其应用于任何表 - 使用动态SQL生成上面显示的模式。

答案 1 :(得分:9)

表不应该

---------
| a | b |
---------
| a | b |
---------

逆时针旋转45度是这样的吗?

-------------
|   | b |   |
-------------
| a |   | b |
-------------
|   | a |   |
-------------

-------------
| a | b | c |
-------------
| d | e | f |
-------------
| g | h | i |
-------------

类似的东西:

---------------------
|   |   | c |   |   |
---------------------
|   | b |   | f |   |
---------------------
| a |   | e |   | i |
---------------------
|   | d |   | h |   |
---------------------
|   |   | g |   |   |
---------------------

答案 2 :(得分:3)

在SQL中没有直接这样做的简单方法。

我建议您将结果导入到不同的编程环境中,例如Java,PHP,Python或者在此上下文中解决问题,然后(如果需要)将结果放回到DB中。

答案 3 :(得分:0)

SQLServer2008 +选项与CROSS APPLY和PIVOT运算符

CREATE TABLE dbo.test77
 (
  id int IDENTITY, 
  colA char(1), 
  colB char(1), 
  colC char(1)
  )

INSERT dbo.test77
VALUES('a','b','c'),
      ('d','e','f'),
      ('g','h','i')

SELECT [1], [2], [3], [4], [5]
FROM (
      SELECT COALESCE(o.colA, o.colB, o.colC) AS Val,
             'Col' + CAST(ROW_NUMBER() OVER (ORDER BY id) AS nvarchar(1)) AS ColName 
      FROM dbo.test77 t CROSS APPLY (
                                     VALUES(colA, NULL, NULL),
                                           (NULL, colB, NULL),
                                           (NULL, NULL, colC)
                                     ) o(colA, colB, colC)
      ) p
PIVOT (
MAX(Val) FOR ColName IN ([Col1], [Col2], [Col3], [Col4], [Col5], [Col6], [Col7], [Col8], [Col9])
) pvt CROSS APPLY (
                   VALUES ([Col3], NULL, NULL, NULL, NULL),
                          ([Col2], [Col6], NULL, NULL, NULL),
                          ([Col1], [Col5], [Col9], NULL, NULL),
                          ([Col4], [Col8], NULL, NULL, NULL),
                          ([Col7], NULL, NULL, NULL, NULL)
                   ) o([1], [2], [3], [4], [5])

SQLFiddle上的演示