Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Tri conditionnel T-SQL par

CASE est une expression qui renvoie une valeur. Ce n'est pas pour le contrôle de flux, comme IF . Et vous ne pouvez pas utiliser IF dans une requête.

Malheureusement, il existe certaines limitations avec CASE expressions qui rendent encombrant de faire ce que vous voulez. Par exemple, toutes les branches d'un CASE L'expression doit renvoyer le même type ou être implicitement convertible dans le même type. Je n'essaierais pas cela avec des chaînes et des dates. Vous ne pouvez pas non plus utiliser CASE pour spécifier le sens du tri.

SELECT column_list_please
FROM dbo.Product -- dbo prefix please
ORDER BY 
  CASE WHEN @sortDir = 'asc' AND @sortOrder = 'name' THEN name END,
  CASE WHEN @sortDir = 'asc' AND @sortOrder = 'created_date' THEN created_date END,
  CASE WHEN @sortDir = 'desc' AND @sortOrder = 'name' THEN name END DESC,
  CASE WHEN @sortDir = 'desc' AND @sortOrder = 'created_date' THEN created_date END DESC;

Une solution sans doute plus simple (surtout si cela devient plus complexe) consiste à utiliser SQL dynamique. Pour contrecarrer l'injection SQL, vous pouvez tester les valeurs :

IF @sortDir NOT IN ('asc', 'desc')
  OR @sortOrder NOT IN ('name', 'created_date')
BEGIN
  RAISERROR('Invalid params', 11, 1);
  RETURN;
END

DECLARE @sql NVARCHAR(MAX) = N'SELECT column_list_please
  FROM dbo.Product ORDER BY ' + @sortOrder + ' ' + @sortDir;

EXEC sp_executesql @sql;

Un autre avantage pour le SQL dynamique, malgré tous les discours alarmistes qui se répandent à son sujet :vous pouvez obtenir le meilleur plan pour chaque variation de tri, au lieu d'un seul plan qui s'optimisera en fonction de la variation de tri que vous avez utilisée en premier. Il a également obtenu les meilleurs résultats universels dans une récente comparaison de performances que j'ai effectuée :

http://sqlperformance.com/ordre-conditionnel-par