Sélection de la table où une colonne contient plusieurs types de données comme varchar

J'ai une table de journal qui enregistre les changements dans datatables dans un tableau à un certain nombre de champs de différents types de données. Il enregistre le nom du champ, les valeurs avant et après l'logging et plus encore. La table de données ressemble à ceci:

FieldName Before After Category lx mt AskingPrice 9.50 10.00 Name Paul Paula AskingPrice 7.20 9.10 Category za pz 

Ainsi, les types de données dans les colonnes Avant et Après varient. Lorsque j'essaie d'écrire une requête pour sélectionner où le champ est = AskingPrice et que la valeur After est supérieure à la valeur Before, elle est erronée avec une conversion de type de données. Après l'erreur, il donne les résultats corrects, mais je suppose que l'erreur est liée à la vérification préalable d'un type de données dans la colonne, mais en choisissant la première ligne. Le code SQL que j'utilise est le suivant:

 SELECT FieldName, Before, After FROM Table WHERE Field = 'dblAskingPrice' and Before > After 

Même si je jette les valeurs, les erreurs ..

 SELECT FieldName, Before, After FROM Table WHERE Field = 'dblAskingPrice' and Cast(Before as Numeric) > Cast(After as Numeric) 

Maintenant, je peux faire une sélection à l'intérieur d'un autre pour sélectionner les champs et la seconde sélectionner pour lancer et comparer, mais notre logiciel ne permet pas de sélectionner une déclaration de sélection.

Y at-il un moyen que je peux get cela dans une déclaration select sans erreur?

Les bases de données SQL ne garantissent pas que les éléments de command de la clause WHERE sont évalués.

Je le répète: les bases de données SQL ne garantissent pas l'évaluation des éléments de la command dans la clause WHERE.

Au lieu des éléments de command apparaissent dans votre command SQL, une database examinera généralement chaque condition et essaiera d'appliquer les conditions dans l'ordre qui, selon elle, produira le résultat le plus rapide et le less cher … généralement, les éléments qui correspondent le mieux à un index ou sont les plus ressortingctives seront appliquées en premier, avec d'autres articles à venir plus tard. Mais vous ne pouvez pas non plus countr sur ce comportement, car l'optimiseur de requêtes peut faire des choses étranges et inattendues basées sur les statistics et la charge du moment.

Cela signifie qu'il est possible d'essayer Cast(Before as Numeric) avant d' évaluer l'expression Field = 'dblAskingPrice' qui vous limite aux loggings dont vous savez qu'ils peuvent être lancés.

Vous pouvez influencer ceci en ayant un bon index sur FieldName,Before,After , mais vous ne pouvez pas garantir les choses de cette façon, d'autant plus que l'opération CAST() ne correspondra généralement pas à l'index. Un index filtré pourrait également aider, mais encore une fois: ce n'est pas une garantie.

Vous pouvez parfois contourner ce problème avec une requête nestede, CTE ou une vue qui inclut uniquement certains loggings:

 SELECT FieldName, Before, After FROM ( SELECT * FROM [Table] WHERE FieldName = 'dblAskingPrice' ) x WHERE Cast(Before as Numeric) > Cast(After as Numeric) 

Mais la meilleure solution consiste généralement à réparer le schéma brisé. Dans ce cas, je suggère que la manière de réparer le schéma consiste à abandonner complètement la table et à activer la fonctionnalité de capture de données de changement qui fait maintenant partie de Sql Server Standard Edition et utilise les fonctions d'audit construit dans Sql Server.

Vous pouvez utiliser un cte ici pour filterr les lignes qui vous intéressent. Ensuite, vous pouvez le convertir en décimal. Quelque chose comme ça.

 create table #something ( FieldName varchar(25) , Before varchar(25) ,After varchar(25) ) insert #something select 'Category', 'lx', 'mt' union all select 'AskingPrice', '9.50', '10.00' union all select 'Name', 'Paul', 'Paula' union all select 'AskingPrice', '7.20', '9.10' union all select 'Category', 'za', 'pz'; with MyCte as ( select * from #something where FieldName = 'AskingPrice' ) select * from MyCte where CONVERT(decimal(7, 2), After) > CONVERT(decimal(7, 2), Before);