41 votes

Comment faire pivoter un tableau de 45 degrés et enregistrer le résultat dans un autre tableau ?

J'ai une table.

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

Je veux le faire pivoter de 45 degrés (dans le sens des aiguilles d'une montre ou dans le sens inverse) et le sauvegarder dans une autre table. Par exemple, si je le fais pivoter de 45 degrés dans le sens inverse des aiguilles d'une montre, ce sera.. :

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

Un autre exemple, quand je fais pivoter

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

Il passera à

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

Comment le faire dans SQL ?

0 votes

@Richard J'utilise SQL Server 2005 ou 2008.

2 votes

Puis-je savoir à quoi sert la rotation des valeurs de la table à 45 degrés ?

68voto

RichardTheKiwi Points 58121

Un exemple entièrement fonctionnel (pour SQL Server 2005+)
Si vous en avez besoin pour un autre système, il existe des équivalents pour les pièces du puzzle ci-dessous

  • nombre_de_rangs()
  • dense_rank()
  • un/pivot

Vous pouvez trouver les équivalents dans d'autres questions Stackoverflow. Par exemple, les deux premières sont bien supportées par Oracle et 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 vous devez l'appliquer arbitrairement à n'importe quelle table, utilisez le SQL dynamique pour générer le modèle présenté ci-dessus.

6 votes

Merci Richard, tu es vraiment un gourou du SQL !

14 votes

C'est l'une des choses les plus intelligentes que j'ai vues sur SO. Même pour une valeur purement théorique, j'aimerais voir cela dans un blog expliqué et généralisé pour les multiples de 45 degrés. Brillant Richard. Désolé si j'ai l'air d'un fanboy, mais je suis vraiment stupéfait par cela :)

2 votes

Pour obtenir la sortie de ypercube, changez targetCol = ROW_NUMBER().. a targetCol = ABS(3 - (row+col-1))-1+2*ROW_NUMBER().. J'ajouterai d'autres commentaires si l'inspiration me vient pour développer la réponse.

9voto

ypercube Points 62714

La table ne devrait-elle pas

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

tourné de 45 degrés dans le sens inverse des aiguilles d'une montre, serait comme ça ?

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

et le

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

quelque chose comme :

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

24 votes

Non, mais je n'ai pas pu coller ces tableaux dans un commentaire. Nous méritons une description claire du problème avant d'essayer de répondre, n'est-ce pas ?

5 votes

Ypercube - une étape de plus (affleurant à gauche) et vous aurez la structure de la question

0 votes

@Richard : Je vois la lumière maintenant, thnx !

3voto

aioobe Points 158466

Il n'y a pas de moyen simple de le faire directement en SQL.

Je vous suggère d'importer le résultat dans un autre environnement de programmation, tel que Java, PHP, Python ou autre, de résoudre le problème dans ce contexte, puis (si nécessaire) de remettre le résultat dans la base de données.

0 votes

Whoosh... le son du point de tout ça volant au-dessus de la tête de quelqu'un à grande vitesse. C'est la même raison pour laquelle les gens font des choses comme este !

1voto

Option pour SQLServer2008+ avec les opérateurs CROSS APPLY et 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])

Démonstration sur SQLFiddle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X