2010-10-14 6 views
2

J'ai besoin de construire une chaîne de Nom, Prénom, Initiale selon les règles suivantes:SQL - concaténation de champ, en fonction de la variable

  1. Si le Nom est unique, juste retour le Nom
  2. Si le nom dernier n'est pas unique, mais la première lettre du nom est d'abord le retour unique Nom + première lettre de Prénom
  3. Si le Nom et premier lette r du prénom sont non unique, renvoyer le nom + la première lettre de Prénom + Moyen Initial.

Par exemple, la table peut être:

MDC MDLast  MDFirst  MDInit 
    3 Jones  Fred   A  
    21 Smith  Sam   D 
    32 Brown  Tom   E 
    42 Brown  Ted   A 
    55 Smith  Al   D 

La requête doit retourner:

MDC MDFormattedName  
3 Jones 
21 Smith S 
32 Brown TE 
42 Brown TA 
55 Smith A 

J'ai écrit une requête qui fonctionne presque, mais il utilise plusieurs imbriquées requêtes, et aura encore besoin de plusieurs autres pour (éventuellement) faire une solution viable, et est si inefficace. Je suis sûr qu'il existe un moyen «approprié» pour implémenter cela (pour SQL Server 2005, BTW).

C'est ce que j'ai jusqu'ici. Cela ne fonctionne pas, en raison des agrégations que je perds les ID peuvent ne pas faire la jointure finale pour obtenir des paires ID/Nom.

select 
    CASE 
     WHEN CountLastFirst > 1 THEN 
      CASE WHEN MDInit IS NOT NULL THEN MDLastFirst + LEFT(MDInit,1) ELSE MDLastFirst END 
     WHEN CountLastFirst = 1 AND CountLast > 1 THEN MDLastFirst 
     ELSE MDLast 
    END as MDName 

FROM 

(

select x.MDLast, CountLast, MDLastFirst, CountLastFirst FROM 
(
select MDLast,Count(MDLast) as CountLast FROM 
MDList 
GROUP BY MDLast) as x 

INNER JOIN 
(select MDLast, MDLastFirst,Count(MDLastFirst) as CountLastFirst FROM 
(
select MDLast, 
MDLast + ' ' + LEFT(MDFirst,1) as MDLastFirst 
From MDList 
) as a 
GROUP BY MDLastFirst, MDLast) as y ON x.MDLast = y.MDLast 
) as z 

Répondre

1

En supposant un nom de table de MDCTable, cela devrait fonctionner:

SELECT MDCTable.MDC, 
    CASE MDCCount.NameCount 
    WHEN 1 
    THEN MDCTable.MDLast 
    ELSE  
     CASE MDFormat1Count 
     WHEN 1 
     THEN MDFormat1.MDFormat1Name 
     ELSE MDCTable.MDLast + ' ' + upper(left(MDCTable.MDFirst, 1)) + 
        MDCTable.MDInit 
     END 
    END AS MDFormattedName 
FROM MDCTable 
INNER JOIN 
(
    SELECT COUNT(MDLast) as NameCount, MDLast 
    FROM MDCTable 
    GROUP BY MDLast 
) MDCCount ON MDCCount.MDLast = MDCTable.MDLast 
INNER JOIN (
    SELECT COUNT(MDLast + left(MDFirst, 1)) as MDFormat1Count, MDLast + ' ' + 
     left(MDFirst, 1) AS MDFormat1Name 
    FROM MDCTable 
    GROUP BY MDLast + ' ' + left(MDFirst, 1) 
) MDFormat1 ON MDCTable.MDLast + ' ' + left(MDCTable.MDFirst, 1) = 
    MDFormat1.MDFormat1Name 
ORDER BY MDCTable.MDC 
+0

Très bien, merci. Je n'ai jamais utilisé une expression dans une clause ON auparavant, c'est une bonne technique à connaître. J'essayais de comprendre comment rejoindre l'indice MDC, mais il n'y avait pas de moyen évident de le faire. – BridgetG

0

Avez-vous envisagé d'effectuer cette opération dans votre application plutôt que directement dans une instruction SQL? Sauf si vous avez une bonne raison de le faire directement en SQL, c'est presque toujours l'approche préférable pour des situations comme celle-ci.

+0

La liste des noms est accessible à partir d'un tas de sources, y compris procs stockées, des programmes VB, les requêtes d'accès, les programmes SAS, etc. En fournissant dans une vue, il résout un tas de problèmes à la fois. Peut-être pas le plus efficace, mais re-travailler toutes ces applications n'est pas pratique. – BridgetG

Questions connexes