T-SQL en sélectionnant des valeurs qui correspondent à ISNUMERIC et sont également dans une plage spécifiée. (Plus Linq to SQL)

StackOverflow https://stackoverflow.com/questions/2558088

Question

Je suis en train de sélectionner des lignes d'une table où l'une des colonnes (NVARCHAR) est dans une plage numérique.

SELECT ID, Value
FROM Data
WHERE ISNUMERIC(Value) = 1 AND CONVERT(FLOAT, Value) < 66.6

Malheureusement, dans le cadre de la spécification SQL les clauses et ne disposent pas de court-circuiter (et ne pas sur MSSQL serveur EE 2008). Plus d'infos: La clause SQL WHERE court-circuit évalué

Ma prochaine tentative était d'essayer de voir si je pouvais obtenir une évaluation retardée du CONVERT

SELECT ID, Value
FROM Data
WHERE (CASE WHEN ISNUMERIC(Value) = 1 THEN CONVERT(FLOAT, Value) < 66.6 ELSE 0 END)

mais je ne peux pas sembler utiliser un <(ou toute comparaison) avec le résultat d'une CONVERT. Il échoue avec l'erreur

Incorrect syntax near '<'.

Je peux sortir avec

SELECT ID, CONVERT(FLOAT, Value) AS Value
FROM Data
WHERE ISNUMERIC(Value) = 1

Donc, la solution évidente consiste à envelopper toute instruction select dans un autre SELECT et WHERE et retourner les valeurs converties de la sélection et le filtre intérieur là où la sélection externe. Malheureusement, c'est là mon problème LINQ to SQL est. Je suis filtrage non seulement par une plage mais potentialy par beaucoup, ou tout simplement par l'existance du dossier (il y a des sélections de plage de dates et des comparaisons que j'ai laissé de côté. )

Essentiellement, je voudrais être en mesure de générer quelque chose comme ceci:

SELECT ID, TypeID, Value
FROM Data
WHERE (TypeID = 4 AND ISNUMERIC(Value) AND CONVERT(Float, Value) < 66.6) 
      OR (TypeID = 8 AND ISNUMERIC(Value) AND CONVERT(Float, Value) > 99)
      OR (TypeID = 9)

(avec d'autres clauses dans chacune de celles où les options.) Cela ne fonctionne pas bien si je filtre les valeurs non-ISNUMERIC dans une sélection interne.

Comme je l'ai mentionné que je utilise LINQ to SQL (et PredicateBulider) pour construire ces requêtes mais malheureusement

Datas.Where(x => ISNUMERIC(x.Value) ? Convert.ToDouble(x.Value) < 66.6 : false)

est convertie en ce qui ne passe pas le problème initial.

WHERE (ISNUMERIC([t0].[Value]) = 1) AND ((CONVERT(Float,[t0].[Value])) < @p0)

Mon dernier recours devra être à la jointure externe contre une double sélection sur la même table pour chacune des comparaisons, mais ce n'est pas vraiment une solution d'idée. Je me demandais si quelqu'un a des problèmes similaires courir dans le passé?

Était-ce utile?

La solution

Je ne pense pas que la question est lui-même et, mais plutôt la convertion de NVARCHAR FLOAT

Jetez un oeil à l'exemple suivant

DECLARE @Table TABLE(
        Value NVARCHAR(10)
)

INSERT INTO @Table SELECT '1'
INSERT INTO @Table SELECT '100'
INSERT INTO @Table SELECT 'A'

SELECT  *
FROM    @Table
WHERE   ISNUMERIC(Value)= 1 AND CAST(CAST(Value AS VARCHAR(10)) AS FLOAT) > 50

SELECT  *
FROM    @Table
WHERE   ISNUMERIC(Value)= 1 AND CAST(Value AS FLOAT) > 50

La dernière sélection est où je reçois l'erreur indiquant

  

Msg 8114, niveau 16, état 5, ligne 13   Erreur de conversion de type de données nvarchar à   flotteur.

Mais les premiers travaux sélectionnez fin.

scroll top