2010-06-16 15 views
5

Tengo una tabla SQL con una columna llamada FullName que contiene, por ejemplo, "John Smith".¿Cómo ordenar por apellido en una columna de nombre completo?

¿Cómo se pueden ordenar los datos por el apellido que aparece en la columna FullName?

Para un nombre largo como "Laurence John Fishburne", me gustaría ordenar los datos por la palabra "Fishburne".

Así, los nombres se almacenan en el orden

  • Nombre
  • segundo nombres
  • Apellido

estoy usando Microsoft SQL Server 2005.

+1

Definir apellido. Mi nombre es "Robert Henry Smith". –

+0

@Dominic: Probablemente tenga que ser la última palabra del siguiente carácter de espacio. Por supuesto, habrá excepciones, pero eso probablemente funcione para la mayoría de los nombres. – FrustratedWithFormsDesigner

+0

He aclarado en la pregunta. – GateKiller

Respuesta

1

En caso de duda, hágalo usted mismo:

Select 
* 
From 
Users 
Order By 
LTrim(Reverse(Left(Reverse(FullName), CharIndex(' ', Reverse(FullName))))) Asc, 
FullName Asc -- Fall-over for when there isn't a last name 
0

Realmente depende de cómo se almacenan los nombres. Asumiendo "Apellido, Nombre" que podría hacer algo como

order by substring(0, charindex(',', FullName)) 

Puede que tenga que jugar con él un poco, pero creo que debería funcionar.

+1

y, además, si LastName es el símbolo más a la derecha de la cadena, entonces use la función reverse() junto con la solución anterior. –

+3

Por favor, vuelva a leer la pregunta. Además, su sintaxis para la función de subcadena no es válida. – GateKiller

+0

@GateKiller: mi respuesta fue escrita antes de la nueva aclaración en la pregunta original. – AllenG

1
create table foo(fullname varchar(100)) 
go 

insert into foo values ('Harry Smith'); 
insert into foo values ('John Davis'); 
insert into foo values ('Allision Thomas Williams'); 

SELECT fullname 
    , REVERSE(left(REVERSE(fullname), charindex(' ',REVERSE(fullname))-1)) 
    FROM foo 
ORDER BY REVERSE(left(REVERSE(fullname), charindex(' ',REVERSE(fullname))-1)) 

Salida:

fullname     (No column name) 
John Davis     Davis 
Harry Smith     Smith 
Allision Thomas Williams Williams 
+0

no necesita usar tantas llamadas a función (REVERSE + left + REVERSE + charindex + REVERSE) para determinar la última cadena de FullName. Un solo RIGHT + CHARINDEX + REVERSE debería ser todo lo que necesita, vea mi respuesta. –

7

Me gustaría hacer algo como:

SELECT FullName 
FROM TABLE 
ORDER BY REVERSE(SUBSTRING(REVERSE(FullName), 0, CHARINDEX(' ', REVERSE(FullName)))) 
+4

aunque no es la solución más eficiente/óptima, esto funciona, ¿por qué el -1? –

2

probar esto, se utiliza el número mínimo de funciones para encontrar el último espacio en FullName s Tring, lo que debería mejorar el rendimiento:

DECLARE @YourTable table (FullNamevarchar(30)) 

INSERT @YourTable VALUES ('Harry Smith'); 
INSERT @YourTable VALUES ('John Davis'); 
INSERT @YourTable VALUES ('Allision Thomas Williams'); 

SELECT 
    FullName 
     ,RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName)) - 1) AS SortBy 
    FROM @YourTable 
    ORDER BY RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName)) - 1) 

SALIDA:

FullName      SortBy 
------------------------------ ------------------------------ 
John Davis      Davis 
Harry Smith     Smith 
Allision Thomas Williams  Williams 

(3 row(s) affected) 

Para el mejor rendimiento y la especie más precisa, es necesario dividir el nombre en los campos Nombre, MiddleName, y Apellido. Solo el usuario que ingresa los datos puede realmente entender qué parte de FullName es el apellido.

+0

Esto falla si la columna solo tiene un nombre. – GateKiller

+0

@GateKiller, use esto, funcionará para un nombre NULL y un nombre sin espacios: 'DERECHA (nombre completo, ISNULL (NULLIF (CHARINDEX ('', REVERSE (nombre completo)) - 1, -1), LEN (nombre completo))) ' –

1

Esto va a hacer el truco:

create table #tmpTable 
(
    ID int identity(1,1) primary key, 
    FullName varchar(100) not null 
); 

insert into #tmpTable(FullName) values('Big John Sansom'); 
insert into #tmpTable(FullName) values('Mike Douglas Reid'); 
insert into #tmpTable(FullName) values('First Second Last'); 
insert into #tmpTable(FullName) values('JustOneTokenForName'); 

select 
    FullName, 
    LastName = case 
     when CHARINDEX(FullName,' ') = 0 THEN FullName 
     else RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName)) - 1) 
    end 
from #tmpTable 
order by LastName 

drop table #tmpTable 
+0

Esto falla si la columna solo tiene un nombre. – GateKiller

+3

@GateKiller: Tal vez sería útil para todos los lectores si cumpliera los requisitos como estos en su pregunta. La solución ahora se actualizó para incluir este requisito adicional. –

5

en lugar de calcular lo que el apellido es cada vez que desee ejecutar la consulta, se puede tener una columna calculada que persiste el valor real en una columna que puede ser utilizado como lo haría con cualquier otra columna.

ALTER TABLE Customer 
    ADD LastName AS 
     RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName)) - 1) PERSISTED 

esto se suma la columna LastName a su tabla de clientes, utiliza la función especificada para calcular el valor del último nombre, y lo almacena en la tabla física. La palabra clave PERSISTED al final es necesaria para que el valor se guarde en el disco; de lo contrario, se computará cada vez que se ejecute una consulta.

Editar: Para hacer frente a los valores sin espacios:

ALTER TABLE Customer 
    ADD LastName AS 
    case when CHARINDEX(' ', REVERSE(FullName)) > 0 
    then RIGHT(FullName, CHARINDEX(' ', REVERSE(FullName)) - 1) 
    else 
    FullName 
    end 
    PERSISTED 

Aunque se puede jugar con esta función que le servirán para determinar lo que ocurre en este caso. Mi punto es mostrar que las declaraciones de casos se pueden usar. También es posible que desee convertir todas las rutas de salida al mismo tipo para evitar desajustes de tipos.

+0

Esto solo funcionará en SQL Server 2005+ –

+0

Esto falla si la columna solo tiene un nombre. – GateKiller

+0

+1 para sugerir la columna calculada: todas las demás soluciones no podrán usar índices. Aunque la mejor ruta sería utilizar esto como una solución provisional hasta que el nombre se pueda separar en múltiples columnas y el front-end/reports/etc. cambiado para manejar eso. –

0

consulta

SELECT stringrowname FROM tablename 
ORDER BY SUBSTRING_INDEX((stringrowname)," ",-1); 

volverá el orden cadenas por última palabra.

Cuestiones relacionadas