2012-03-06 12 views
13

Básicamente necesito hacer una combinación externa izquierda en 2 tablas (CarePlan y referencias) problema es que necesito la referencia más reciente Si existe, está bien si no.Servidor SQL: UNIÓN EXTERIOR IZQUIERDA con TOP 1 para seleccionar en la mayoría de una fila

que tienen estos 2 consultas 1. une a la CarePlan/mesas de Referencia - CarePlan crea duplicados si hay múltiples referencias para un careplan, o no tiene información de referencia en absoluto (externa izquierda) 2. seleccione la parte superior 1 remisión basado en la fecha, dado un CarePlanId

me gustaría combinar estos 2 así que agarrar todas las CarePlan y sus referencias si es que existe, si lo hace - tome solamente la más reciente de referencia

select * from CarePlan c //query 1 
left outer join Referral r on 
r.CarePlanId = c.CarePlanId 


select top 1 * from Referral r //query 2 
where r.CarePlanId = '1' 
order by ReferralDate desc 

EDITAR :

La primera consulta me da algo como esto:

CarePlanID ReferralId  ReferralDate 
---------- ----------  ------------ 
1    1    05/15/12 
2    NULL   NULL 
1    2    05/10/12 //Old date, dont want this careplan 

La segunda consulta me dará la referencia con la fecha más reciente

ReferralId ReferralDate 
---------- ------------ 
1    05/15/12 

Los datos de referencia, pueden tener 0 o más referencias que pertenecen a una Careplan

ReferralID CarePlanId Date 
---------- ---------- ---- 
1   1    05/15/12 
2   1    05/10/12 

en última instancia quiero una consulta que me da CarePlan con las referencias que tienen la fecha más reciente, o nulo para referencias si es imposible tener que

así:

CarePlanId ReferralId ReferralDate 
---------- ---------- ------------ 
1   1    05/15/12 
2   NULL   NULL 

Gracias - Espero que esto tenga sentido

+0

teniendo problemas para leer lo que quieres, pero creo que lo que necesitas es buscar cómo hacer un cte o una tabla derivada. – HLGEM

+0

¿Puede mostrar los datos de muestra y los resultados deseados? Al igual que @HLGEM, no está claro dónde estás comenzando y hacia dónde quieres llegar. –

+0

Necesita una aplicación cruzada. – usr

Respuesta

38
select * 
from CarePlan c 
outer apply (
    select top 1 * --top N rows 
    from Referral r 
    where r.CarePlanId = c.CarePlanId --join condition 
    order by /*fill this in!*/ 
) x 

Tenga en cuenta que esto obliga a una combinación de bucle debido al optimizador debilidades hasta e incluyendo la versión 2014.

1

Sólo una conjetura. No estoy seguro si EF tendrá problemas con la sintaxis de CTE. ¿Puede obligar a EF a llamar a un procedimiento almacenado para que no esté esposado por el subconjunto de funcionalidades admitidas por EF?

;WITH r AS 
(
    SELECT CarePlanId, MAX(ReferralDate) 
    FROM dbo.Referrals GROUP BY CarePlanId 
) 
SELECT * FROM dbo.CarePlan AS c 
LEFT OUTER JOIN r 
    ON r.CarePlanId = c.CarePlanId; 
+0

lo siento - supongo que es más una pregunta general de SQL, Entity Framework no debería importar aquí - al menos eso espero. También espero que los planes de atención devueltos sean distintos (solo se utiliza uno con la referencia más reciente) – Jerrold

+0

Solo usted puede decirnos esto último: ¿ha confirmado la ejecución de la consulta? ¿Devuelve los resultados que espera? Si nos muestra los datos de muestra y lo que espera para el resultado, es mucho más fácil para nosotros probar nuestras respuestas antes de arrojarlos sobre la pared. También ahorra tiempo a todos. –

6

Sé que esta pregunta es más viejo, pero hay otro enfoque que siento es bajo -utilizado:

Puede unir las tablas consigo mismo y utilizar un operador para buscar el registro "más reciente".

respuesta

SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate 
FROM CarePlan CP 
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId 
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate 
WHERE R_NEWER.ReferralId IS NULL 

resultados:

CP.CarePlanId R.ReferralId R.ReferralDate 
----------  ----------  ------------ 
1    1    05/15/12 
2    NULL   NULL 

Explicación

Vamos a descomponerlo. Básicamente está diciendo, para cada registro de referencia, (a la izquierda), únase a cada otro registro de referencia que esté asociado con el mismo CarePlanId pero SÓLO donde haya un ReferralDate más reciente.

Ésta es la consulta sin la cláusula where (junto con algo de información, además de la mesa R_NEWER):

SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate, R_NEWER.ReferralId, R.NEWER.ReferralDate 
FROM CarePlan CP 
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId 
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate 

Aquí es el resultado de esa consulta:

CP.CarePlanId R.ReferralId R.ReferralDate R_NEWER.ReferralId R_NEWER.ReferralDate 
----------  ----------  ------------ ------------  ------------  
1    1    05/15/12  NULL    NULL 
2    NULL   NULL   NULL    NULL 
1    2    05/10/12  1     05/15/12 

Como se puede ver , solo el Id. de referencia 2 (3er registro anterior) encontró un registro "más reciente" para unirse en la tabla de referencia (es decir, ID de referencia 1). Id. De referencia 1 (1er registro anterior) NO encontró una referencia "más reciente" (para el mismo CarePlanId).

Por lo tanto, con esto en mente, ahora sólo nos queda añadir la cláusula where de vuelta:

SELECT CP.CarePlanId, R.ReferralId, R.ReferralDate, R_NEWER.ReferralId, R.NEWER.ReferralDate 
FROM CarePlan CP 
LEFT OUTER JOIN Referral R ON R.CarePlanId = CP.CarePlanId 
LEFT OUTER JOIN Referral R_NEWER ON R.CarePlanId = R_NEWER.CarePlanId AND R.ReferralDate < R_NEWER.ReferralDate 
WHERE R_NEWER.ReferralId IS NULL 

y obtenemos:

CP.CarePlanId R.ReferralId R.ReferralDate R_NEWER.ReferralId R_NEWER.ReferralDate 
----------  ----------  ------------ ------------  ------------  
1    1    05/15/12  NULL    NULL 
2    NULL   NULL   NULL    NULL 

En este punto, basta con retirar sus columnas R_NEWER de su SELECT como ya no se necesitan y tienes tu respuesta.

Es importante recordar que el "dónde" se aplica DESPUÉS de que se hayan producido las uniones, pero la instrucción ON se produce en el momento de la unión. Para hacer esto más comprensible para mí, siempre trato de escribir los SELECT y JOINs y devolver las columnas de cada tabla a la que me estoy uniendo y luego agregar mis cláusulas WHERE una vez que tenga una imagen clara de lo que se devuelve.

Advertencia Este enfoque funciona muy bien en la mayoría de los casos, pero es posible tener las filas duplicadas si tuviera 2 referidos (por el mismo CarePlanId) con la fecha de 05/15/12 y que la fecha era el " más reciente." Para solucionarlo, puede ampliar su (s) unión (es) para limitar basándose en el ReferralId "más alto" si surge esa situación.

Cuestiones relacionadas