Est-il possible de commander une table avec un numéro de colonne en cas de déclaration? Voici le code
;WITH
Table1 AS (....),
Table2 AS (....)
INSERT INTO #temp
SELECT TOP 50
one.id,
one.sales,
two.count,
one.sales * two.count as 'Volume %'
FROM Table1 one,
INNER JOIN Table2 two on one.id = two.id
ORDER BY
CASE @order
WHEN 1 THEN
7 ---Column number here since [Volume %] giving me an error
WHEN 2 THEN
10 ---Column number
END
DESC
4 Réponses :
si ce sont des nombres, vous pouvez essayer
SELECT TOP 50
one.id,
one.sales,
two.count,
one.sales * two.count as 'Volume %'
FROM Table1 one,
INNER JOIN Table2 two on one.id = two.id
ORDER BY
CASE @order
WHEN 1 THEN
one.sales * two.count ---Column number here since [Volume %] giving me an error
WHEN 2 THEN
two.count ---Column number
END
DESC
ou une sorte de piratage similaire pour les chaînes même
avez-vous essayé
.... ORDER BY (CASE WHEN @ORDER = 1 THEN 1 ELSE 0 END ) * col1 + (CASE WHEN @ORDER = 2 THEN 1 ELSE 0 END ) * col2 DESC
Puisque vous avez mentionné dans un commentaire que vous essayez d’ajouter uniquement les 50 premiers enregistrements par% de volume par ordre décroissant à la table temporaire , vous pouvez faire quelque chose comme ceci:
;WITH
Table1 AS (....),
Table2 AS (....)
INSERT INTO #temp
SELECT TOP 50
one.id,
one.sales,
two.count,
one.sales * two.count as 'Volume %'
FROM Table1 one,
INNER JOIN Table2 two on one.id = two.id
ORDER BY [Volume %] DESC
Êtes-vous sûr qu'un alias de colonne Volume% est disponible pour la clause ORDER BY ?
Oui, mais il doit être entre crochets ( [Volume%] )
Vous avez oublié que j'ai une variable qui change. @Ordre
Oui, cela ne tient absolument pas compte de la nécessité de classer par différentes colonnes en fonction du paramètre @order .
La raison pour laquelle j'ai ignoré @order est que OP a commenté que "J'essaie d'ajouter uniquement les 50 premiers enregistrements par volume% par ordre décroissant à la table temporaire" et qu'il n'y a qu'une seule façon de trier [Volume %] .
J'ai fait quelques tests et appris que si un ORDER BY simple peut référencer des alias de colonne (même ceux avec des espaces), une expression CASE dans ORDER BY ne le peut pas. Je n'ai jamais vu cela documenté nulle part, mais je l'ai testé moi-même.
Peu importe que vous ayez un caractère spécial dans votre alias. Si vous aviez seulement fait:
ORDER BY CASE @order WHEN 1 THEN one.sales * two.count
Vous obtiendriez toujours une erreur avec:
ORDER BY CASE @order WHEN 1 THEN Volume
Et je suppose que c'est la même chose raison pour laquelle vous ne pouvez pas utiliser de numéros de colonne.
Ma suggestion comme moyen infaillible de résoudre ce problème est:
one.sales * two.count as Volume
J'y pensais. Je ne sais pas pourquoi order by fonctionne comme ça. J'accepterai votre réponse car elle donne des explications. Un autre problème est que j'ai plusieurs colonnes en cours de calcul et que j'utilise aussi l'instruction case . Si j'ajoute ceux-ci dans l'ordre, ce sera un gros désordre. J'ai créé une autre table temporaire dans laquelle j'insère le top 50 de la table que je génère sans commander. Merci quand même!
Eh bien, le premier niveau "pourquoi" est que le fait d'avoir une expression CASE dans ORDER BY oblige l'analyseur à déterminer ORDER BY avant que les alias ne soient attribués, tandis qu'un ORDER BY simple est analysé après b> les alias sont attribués. Le deuxième niveau, pourquoi l'analyseur le fait-il de cette façon? Aucune idée.
Et le plus étrange, c'est que je n'ai pas pu trouver de question similaire à celle-ci. Je me demande comment personne n'a eu un problème comme celui-ci. Depuis que j'ai commencé sql il y a tout juste un an.
@TabAlleman Il existe de la documentation sur les alias de colonne dans les expressions triées par . J'ai ajouté une réponse avec les détails.
Depuis le documentation pour ORDER BY :
Si la clause ORDER BY fait référence à un alias de colonne de la liste de sélection, l'alias de colonne doit être utilisé de manière autonome et non dans le cadre de certains expression dans la clause ORDER BY ...
Un nom de colonne, et non un alias , peut être utilisé dans une expression, par exemple case.
En plus:
order_by_expression
Spécifie une colonne ou une expression sur laquelle trier l'ensemble de résultats de la requête. Une colonne de tri peut être spécifiée sous forme de nom ou alias de colonne, ou un entier non négatif représentant la position de la colonne dans la liste de sélection.
Cela signifie que si vous commandez par 1 , l'ordre sera déterminé par la première colonne de la liste de sélection. En utilisant une expression, par ex. order by Length * 0 + 1 , ne sera pas ordonné par la première colonne même si l'expression se trouve être évaluée à 1 .
Une technique courante pour déplacer les valeurs NULL après les autres est:
select Sample from Samples order by case when Sample is NULL then 1 else 0 end, Sample;
Vous ne voudriez pas que l'expression case sélectionne une colonne par position.
A part: Je dirais que l'analyseur a un bogue: order by 1 ordonne correctement par la première colonne de résultat. L'utilisation de l'expression order by (1) ordonne également selon la première colonne de résultat mais devrait générer la même erreur que order by 1 + 0 : "Une expression constante a été rencontrée dans le ORDER BY list, position 1. "
Cela peut faire partie d'un modèle d'analyse bâclée d'expressions simples: SELECT INTO avec la colonne IDENTITY dans l'expression est géré de manière incohérente .
p>
Une raison pour ne pas utiliser le nom de la colonne?
@Sami a essayé mais m'a donné une erreur en disant
nom de colonne invalideVous pouvez trier par numéro de colonne puisque le nombre est dans la plage, donc si vous avez 3 colonnes et que vous commandez par 4, cela générera une erreur car il n'y a pas de 4 colonnes. Il n'est pas non plus nécessaire d'utiliser CASE simplement
ORDER BY (SELECT @Variable)CASE est une expression, elle est utilisée pour renvoyer une valeur. Vous essayez d'utiliser cela pour contrôler la logique, ce qui n'est pas possible. Et ne triez pas par position ordinale, il est très sujet aux erreurs si votre requête change à chaque fois. Avez-vous besoin d'insérer pour contrôler la valeur de l'identité? Sinon, ajouter de l'ordre à votre insertion est inutile car une table est un ensemble non ordonné.
Il n'y a que quatre colonnes ...
7ou10sont hors de portée, n'est-ce pas?Utilisez un deuxième CTE pour nommer les colonnes souhaitées.
@TheImpaler ce code n'est qu'un exemple. Dans mon code actuel, j'ai plus de 10 cols
@TabAlleman étrange, je fais par
[Volume%]et il lance une erreur@SeanLange J'essaie d'ajouter uniquement les 50 premiers enregistrements par
Volume%dans l'ordre décroissant à la table temporaire@AntihypeBird vous avez raison, cela fonctionne dans un simple
ORDER BY, mais des erreurs dans leORDER BY CASE ...Depuis ref : order_by_expression Spécifie une colonne ou une expression sur laquelle trier l'ensemble de résultats de la requête. Une colonne de tri peut être spécifiée comme un nom ou un alias de colonne, ou un entier non négatif représentant la position de la colonne dans la liste de sélection. (Je souligne.) Je suppose que cela signifie qu'une expression générale ne sera pas traitée comme un numéro de colonne ordinale, ce doit être un entier explicite.
À part: Le résultat d'une expression
casedoit être un type de données. Si vos colonnes de tri sont de types de données différents, elles devront être converties, implicitement ou explicitement, en un seul type de données commun.