2011-02-26 12 views
39

Tengo una mesa.Cómo rotar una tabla 45 grados y guardar el resultado en otra tabla?

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

Quiero girarlo 45 grados (en sentido horario o antihorario) y guardarlo en otra tabla. Por ejemplo, si girarlo 45 grados en sentido antihorario, será:

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

Otro ejemplo, cuando puedo rotar

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

Se va a cambiar a

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

Cómo hacer esto en SQL?

+0

@Richard que estoy usando SQL Server 2005 o 2008. –

+2

se puede saber cuál es el propósito de hacer girar el tabla de valores a 45 grados? – RGS

Respuesta

64

Un ejemplo de trabajo completo (para SQL Server 2005 +)
Si lo necesita para otro sistema, hay equivalentes para las piezas del rompecabezas debajo de

  • row_number()
  • DENSE_RANK()
  • un/pivote

Puede encontrar los equivalentes de otras preguntas Stackoverflow. Por ejemplo, los dos primeros son bien compatibles con Oracle y 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 

Si necesita aplicarlo arbitrariamente a cualquier tabla, utilice SQL dinámico para generar el patrón que se muestra arriba.

+5

Gracias Richard, ¡realmente eres un SQL Guru! –

+13

Esta es una de las cosas más inteligentes que he visto en SO. Incluso por un valor puramente teórico, me gustaría ver esto en un blog explicado y generalizado para múltiplos de 45 grados. Brillante Richard. Lo siento si sueno como un fan boy, pero estoy realmente sorprendido por esto :) –

+2

Para obtener la salida de ypercube, cambia 'targetCol = ROW_NUMBER() ..' a 'targetCol = ABS (3 - (row + col-1)) -1 + 2 * ROW_NUMBER() .. 'Agregaré más comentarios si la inspiración puede ampliar la respuesta – RichardTheKiwi

3

No hay una forma simple de hacerlo directamente en SQL.

Le sugiero que importe el resultado en un entorno de programación diferente, como Java, PHP, Python o lo que sea, resuelva el problema en este contexto y luego (si es necesario) devuelva el resultado al DB.

8

¿No debería la tabla

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

girado 45 grados en sentido antihorario a ser así?

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

y la

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

algo como:

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

Esto no es una respuesta. – aioobe

+23

No, pero no pude pegar estas tablas dentro de un comentario. Merecemos una descripción clara del problema antes de intentar responder, ¿verdad? –

+5

ypercube - un paso más (alineado a la izquierda) y tendrá la estructura de pregunta – RichardTheKiwi

0

opción para SQLServer2008 + con la cruz y el pivote SOLICITAR operadores

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]) 

demo en SQLFiddle

Cuestiones relacionadas