2008-12-03 7 views
2

Casse-tête d'un collègue de travail que je ne peux pas comprendre ...données ne filtre pas avant une jointure

update btd.dbo.tblpayroll 
set  empname = (select b.Legal_Name 
        from (SELECT Legal_Name, 
             Employee_ID 
           FROM  Com.dbo.Workers 
           WHERE  isnumeric(Employee_ID) = 1 
          ) b 
        where b.Employee_ID = empnum 
          and b.Legal_name is not NULL 
       ) 
where empname is NULL 

Msg 245, niveau 16, état 1, ligne 1 La conversion a échoué lors de la conversion varchar valeur 'N0007' au type de données int. L'alias de table b serait en fait une vue.

La valeur 'N0007' se trouve dans la table Workers. Je ne vois pas pourquoi on ne filtre pas les résultats qui sont joints.

EDIT:

L'alias ne, en fait, retourner les lignes correctes - donc isNumeric fait le travail.

Répondre

2

Je soupçonne que l'optimiseur tente d'appliquer la clause where de la sélection externe avant la sélection interne. Vraisemblablement, il pense qu'il serait en mesure de faire une recherche d'index sur Employee_ID résultant dans une requête plus rapide dans ce cas. Essayez:

update btd.dbo.tblpayroll 
set  empname = (select Legal_Name 
        from Com.dbo.Workers 
        where isnumeric(Employee_ID) = 1 
          and convert(varchar,Employee_ID) 
          = convert(varchar,empnum) 
          and Legal_name is not NULL) 
where empname is NULL 

Les convertir tous en varchar devrait prendre soin d'elle. Je ne pense pas que ce soit beaucoup moins efficace que ce que vous vouliez initialement puisque l'isnumérique, s'il était fait en premier, aurait forcé une analyse de table de toute façon.

+0

Optimizer chose je pense aussi bien. où b.Employee_ID = CAST (empnum AS VARCHAR) devrait aider –

+0

J'ai essayé de regarder le plan expliquer pour voir si je pourrais le repérer - mais je ne suis pas bien versé dans leur lecture. Votre requête a fonctionné assez bien dans la requête réelle. Merci. – Sam

+0

@Stanislav - Je n'étais pas sûr du type de chacun, alors je pensais que convertir les deux en varchar était le pari le plus sûr. – tvanfosson

0

Peut-être que N est considéré comme un symbole monétaire? Vous pouvez essayer de remplacer IsNumeric avec

LIKE REPLICATE('[0-9]',/*length of Employee_ID*/) 

ou tout simplement

LIKE '[0-9]%' 

si la lettre ne peut pas être au milieu

0

La chose évidente est de forcer l'ordre de comparaison, peut-être en obtenant ensuite le nom d'une vue avec uniquement des ID_personnel numériques, plutôt que la table des travailleurs complète.

+0

Malheureusement la réponse évidente est ce que nous faisions en premier - et cela a étonnamment eu le même comportement. – Sam

Questions connexes