1
votes

Syntaxe incorrecte pour la clause Order by avec plusieurs colonnes

Comment écrire ordre par clause avec plusieurs colonnes dans une instruction case?

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Convert(int,Val) 
 WHEN @T='ABC' Then Convert(nvarchar,Seq)
 ELSE Seq END

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Seq END

Également essayé

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Seq END

Également le code ci-dessous renvoie une erreur:

"Cette instruction donne une erreur:" La conversion a échoué lors de la conversion de la valeur nvarchar 'EX-02-60' en type de données int "lorsque la procédure stockée est exécutée."


4 commentaires

Cette tentative est à l'envers. Mettez la casse expression dans ORDER BY.


Je vous ai déjà dit exactement quoi écrire dans un commentaire sur votre autre question lorsque j'ai suggéré ce changement.


OP Je mets à jour ma réponse pour être claire et pour plus de détails et j'inclus également une démo en direct.


@Damien_The_Unbeliever Oui, vous l'avez fait. Mais j'étais confronté à des problèmes de syntaxe et une autre erreur s'est produite. Par conséquent, j'ai ajouté ce poste en tant que chaîne distincte. Bien que cette question reste ouverte, le code a été optimisé mais les performances restent les mêmes et j'ai également mentionné la même chose dans cette question.


3 Réponses :


1
votes

Je pense que ce que vous recherchez est:

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Convert(int,Val) 
 WHEN @T='ABC' Then Convert(nvarchar,Seq)
 ELSE Seq END

Expliquer pourquoi vos tentatives n'ont pas fonctionné. Premièrement:

WHERE  Type = @T  ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Sequence END

Un CASE est une expression qui renvoie une valeur scalaire . Ici, votre WHEN a essayé de renvoyer 2 valeurs. Ce n'est pas autorisé.

ORDER BY CASE @T WHEN 'ABC' THEN Val END,
         CASE @T WHEN 'ABC' THEN Seq END,
         [Sequence];

Comme CASE renvoie une valeur scalaire, il ne peut renvoyer qu'un seul type de données. L'expression CASE utilise la précédence du type de données, et int a une précédence plus élevée que nvarchar donc Seq serait implicitement converti en un int ; et je risquerais de penser que cela a échoué.


12 commentaires

Cette instruction donne l'erreur: «La conversion a échoué lors de la conversion de la valeur nvarchar 'EX-02-60' en type de données int» lorsque la procédure stockée est exécutée.


Ce ne sera pas le ORDER BY renvoyant cette erreur @ShradhaR. Il n'y a pas de conversions implicites dans ma solution. Cette erreur provient d'un autre endroit de votre SQL que vous ne nous avez pas fourni.


Une conversion explicite Convert (nvarchar, Seq) ne fonctionnera pas dans ce scénario? sinon, pourriez-vous suggérer une meilleure approche?


Je ne sais pas ce que vous voulez dire ici @ShradhaR. Je n'ai pas de conversion explicite ou implicite dans ma solution. L'erreur que vous obtenez (avec le ORDER BY que j'ai fourni) n'est pas due à la clause ORDER BY . C'est ailleurs.


Si vous publiez votre SQL complet , ainsi que DDL dans votre question, nous pouvons vous aider à résoudre ce problème également. Ou peut-être posez-le comme une question distincte.


@sami CASE @T WHEN 'ABC' THEN Val END, renverra le type de données de Val . Si Val est un varchar , alors c'est le type de données qu'il retournera. Le NULL serait implicitement converti en varchar ; un NULL n'a pas le type de données int par défaut. Sinon, une expression comme SELECT CASE WHEN 1 = 1 THEN 'abc' END échouerait.


@Sami. . . C'est la bonne solution et cela explique également pourquoi.


Et j'ai reproduit cette logique, @Sami par une méthode différente. Si @T a une valeur de ABC 'alors les données seront triées (par ordre croissant) par Val , puis Seq , puis enfin Sequence . Si @T a une autre valeur (y compris NULL ), alors les données seront triées par la valeur NULL (donc pas d'ordre), suivie par alors la valeur NULL (encore une fois, pas d'ordre), puis Sequence ; ce qui signifie effectivement que les données seront triées par Séquence . Ce n'est pas parce que l'OP a utilisé la logique CASE ... ELSE que la solution doit le faire.


@Sami Où voyez-vous un casting dans ma solution? Ni CASE @T WHEN 'ABC' THEN Val END, ni CASE @T WHEN 'ABC' THEN Seq END, n'ont de transtypage implicite (ou explicite). Comme je l'ai déjà dit, NULL n'a pas de type de données par défaut et, dans ce cas, sera CAST au type de données de Val et < code> Seq respectivement dans chacune de ces expressions CASE .


@Sami Je n'ai pas de ELSE dans ma logique ... Vous semblez avoir mal lu mon SQL. J'ai édité votre violon DB pour montrer quelle est ma logique. J'ai également modifié les exemples de données pour montrer ce qui se passe lorsque @T n'a pas la valeur 'abc' : db <> violon


@Larnu C'est faux car maintenant vous allez toujours commander par NN, (séquence dans OP Q)


Euh ... @Sami avez-vous lancé le violon. Notez que les 2 jeux de données ont 2 ordres différents ... J'ai essayé, mais clairement cette conversion est terminée / perdue.



0
votes

Le type de données de la valeur dans le ORDER BY doit toujours être le même. Ici, vous obtiendrez l'erreur de conversion car dans le premier cas, le type de données est INT et dans le second, c'est Varchar. SO Pour une manière plus sécurisée, vous pouvez utiliser l'approche suivante

;WITH CTE
AS
(
    SELECT
        RN_Val = ROW_NUMBER() OVER(ORDER BY Val),
        RN_Seq = ROW_NUMBER() OVER(ORDER BY Seq),
        *
        FROM YourTable
)
SELECT
    *
    FROM CTE
        ORDER BY 
        (
            CASE @T
                WHEN 'ABC' THEN RN_Val
                WHEN 'XYZ' THEN RN_Seq
            END
        )


0 commentaires

7
votes

Créons une table qui a vos colonnes

--Fixes--

DECLARE @T VARCHAR(3) = '1'; --Try to change it to ABC too

SELECT *
FROM T
ORDER BY CASE WHEN @T='ABC' THEN Val END, --Take varchar
         CASE WHEN @T='ABC' THEN Seq -- Take INT
              ELSE Sequence -- Take INT
         END;
/*
 IF @T = ABC
 ORDER BY Val, Seq; NOT Sequence
 
 IF @T <> ABC
 ORDER BY ONLY Sequence
*/

Maintenant, regardons votre code et apportons ensuite les conditions:

Voici votre code: p >

--You was trying--

DECLARE @T VARCHAR(3) = 'ABC'; --wil works only when @T <> ABC

SELECT *
FROM T
ORDER BY CASE WHEN @T='ABC' THEN Seq END, --Take INT
         CASE WHEN @T='ABC' THEN Val --Take Varchar
              ELSE Sequence -- Take INT
         END;
  • Si @T = 'ABC alors commandez par Val et Seq ET NE PAS commandez par Séquence .
  • Si @T 'ABC' alors commandez Seulement avec Séquence .

Si vous exécutez cette requête:

 ORDER BY 
 CASE 
 WHEN @T='ABC' Then Val,Seq
 ELSE Sequence END

Cela générera l'erreur suivante si @T = 'ABC' p>

Msg 245 Niveau 16 État 1 Ligne 5

La conversion a échoué lors de la conversion de la valeur varchar 'A' en type de données int.

comme vous obtenez

La conversion a échoué lors de la conversion de la valeur nvarchar 'EX-02-60' en type de données int.

Maintenant, voici ce que vous voulez selon les conditions que vous fournissez:

CREATE TABLE T(
  Val VARCHAR(45),
  Seq INT,
  Sequence INT
);

INSERT INTO T VALUES
('A', 1, 2),
('C', 2, 1),
('B', 3, 3);

Et voici un Démo en direct


3 commentaires

Le code précédent fonctionnait bien pour moi. Je n'ai pas encore testé le dernier que vous avez fourni.


@SRawat Le code précédent fonctionne très bien pour vous car CAST (), mais il ne prend pas la colonne Sequence dans count.


Comment se fait-il que je n'ai pas de moyen de vous contacter sauf pour SO