Una forma sencilla de resolver esto como yo lo veo, es para clasificar los nombres de cada tipo de cada persona independientemente con diferentes señales de clasificación, es decir, por ejemplo, los nombres de pila con positivo clasificaciones, apellidos con resultados negativos. Luego selecciona y pivota los nombres que tienen clasificaciones de 1
, 2
, -1
, -2
. Esto es lo que la consulta podría ser:
WITH ranked AS (
SELECT
*,
rnk =
CASE NameType WHEN 'first' THEN 1 ELSE -1 END *
ROW_NUMBER() OVER (
PARTITION BY PersonId, NameType
ORDER BY NameId
)
FROM PersonNames
WHERE NameType IN ('first', 'last')
)
SELECT
PersonId,
FName1 = [1],
FName2 = [2],
LName1 = [-1],
LName2 = [-2]
FROM (
SELECT
PersonId,
Name,
rnk
FROM ranked
) s
PIVOT (
MAX(Name) FOR rnk IN ([-2], [-1], [1], [2])
) p
Por otra parte, la clasificación apellidos del final podría parecer más apropiado (por lo menos, creo, me podrían preferir lo mejor de esta manera).Así que aquí hay una alternativa a la secuencia de comandos que ocupa apellidos desde el final:
WITH ranked AS (
SELECT
*,
rnk =
CASE NameType WHEN 'first' THEN 1 ELSE -1 END *
ROW_NUMBER() OVER (
PARTITION BY PersonId, NameType
ORDER BY CASE NameType WHEN 'first' THEN 1 ELSE -1 END * NameId
)
FROM PersonNames
WHERE NameType IN ('first', 'last')
),
SELECT
PersonId,
FName1 = [1],
FName2 = [2],
LName1 = ISNULL([-2], [-1]),
LName2 = CASE WHEN [-2] IS NULL THEN NULL ELSE [-1] END
FROM (
SELECT
PersonId,
Name,
rnk
FROM ranked
) s
PIVOT (
MAX(Name) FOR rnk IN ([-2], [-1], [1], [2])
) p
se puede ver que esta versión es un poco más complicado. Por un lado, un cambio de signo tuvo que ser aplicado a NameId
para asegurar su clasificación en diferentes direcciones para diferentes tipos.
Otra cosa es tirar del conjunto de resultados final. Verá, si una persona tiene solo dos o más apellidos, la secuencia de comandos los mostrará en el orden tal como están en la tabla: el elemento anterior al último va al LName1
y el último elemento va al LName2
. Pero en el caso de exactamente un apellido, mi intención era mostrarlo como LName1
, y LName2
para estar vacío (al igual que la primera consulta). Por lo tanto, como puede ver, se tomaron medidas adicionales para garantizar el orden de visualización.
¿Cómo se relacionan 'Person' y' PersonNames'? ¿Hay un 'PersonId' en' PersonNames' que no has mostrado? –
Sí, hay un PersonId en personNames. –
¿Puede darnos el ejemplo de la tabla PersonNames para su Persona? –