Tenemos mesa de citas como se muestra a continuación. Cada cita debe clasificarse como "Nueva" o "Seguimiento". Cualquier cita (para un paciente) dentro de los 30 días de la primera cita (de ese paciente) es Seguimiento. Después de 30 días, la cita vuelve a ser "nueva". Cualquier cita dentro de los 30 días se convierte en "Seguimiento".
Actualmente estoy haciendo esto escribiendo while loop.
¿Cómo lograr esto sin WHILE loop?
Mesa
CREATE TABLE #Appt1 (ApptID INT, PatientID INT, ApptDate DATE)
INSERT INTO #Appt1
SELECT 1,101,'2020-01-05' UNION
SELECT 2,505,'2020-01-06' UNION
SELECT 3,505,'2020-01-10' UNION
SELECT 4,505,'2020-01-20' UNION
SELECT 5,101,'2020-01-25' UNION
SELECT 6,101,'2020-02-12' UNION
SELECT 7,101,'2020-02-20' UNION
SELECT 8,101,'2020-03-30' UNION
SELECT 9,303,'2020-01-28' UNION
SELECT 10,303,'2020-02-02'
fast_forward
cursor probablemente sea su mejor opción, en cuanto al rendimiento.Respuestas:
Necesita usar la consulta recursiva.
El período de 30 días se cuenta a partir de prev (y no, no es posible hacerlo sin recurrencia / actualización peculiar / bucle). Es por eso que todas las respuestas existentes usando solo
ROW_NUMBER
fallaron.demostración de violín db <>
Salida:
Cómo funciona:
Clase similar:
SUM condicional en Oracle : limitar una función con ventana
Ventana de sesión (Azure Stream Analytics)
Total de ejecución hasta que se cumpla una condición específica : actualización peculiar
Apéndice
¡Nunca use este código en producción!
Se podría hacer en ronda "única" (actualización peculiar):
Consulta:
db <> violín actualización peculiar
fuente
RANGE x PRECEDING
cláusula.Podrías hacer esto con un cte recursivo. Primero debe ordenar por fecha de cita dentro de cada paciente. Eso se puede lograr con un cte de rutina.
Luego, en la parte de anclaje de su cte recursivo, seleccione el primer pedido para cada paciente, marque el estado como 'nuevo' y marque la fecha de solicitud como la fecha del registro 'nuevo' más reciente.
En la parte recursiva de su cte recursivo, incremente a la próxima cita, calcule la diferencia en días entre la cita actual y la fecha de la cita 'nueva' más reciente. Si es mayor de 30 días, márquelo como 'nuevo' y restablezca la fecha de la nueva cita más reciente. De lo contrario, márquelo como 'seguimiento' y simplemente pase los días existentes desde la nueva fecha de la cita.
Finalmente, en la consulta base, simplemente seleccione las columnas que desee.
Debo mencionar que inicialmente eliminé esta respuesta porque la respuesta de Abhijeet Khandagale parecía satisfacer sus necesidades con una consulta más simple (después de reelaborarla un poco). Pero con su comentario sobre los requisitos de su negocio y sus datos de muestra agregados, eliminé los míos porque creo que este satisface sus necesidades.
fuente
No estoy seguro de que sea exactamente lo que implementaste. Pero otra opción, que vale la pena mencionar además de usar cte, es usar la tabla temporal y actualizar en "rondas". Así que vamos a actualizar la tabla temporal mientras que todos los estados no están configurados correctamente y generar resultados de forma iterativa. Podemos controlar el número de iteraciones usando simplemente una variable local.
Entonces dividimos cada iteración en dos etapas.
Entonces
Actualizar. Lea el comentario proporcionado por Lukasz. Es, con mucho, la forma más inteligente. Dejo mi respuesta solo como una idea.
fuente
Creo que la expresión común recursiva es una excelente manera de optimizar las consultas evitando bucles, pero en algunos casos puede conducir a un mal rendimiento y debe evitarse si es posible.
Utilizo el código a continuación para resolver el problema y probarlo con más valores, pero le recomiendo que también lo pruebe con sus datos reales.
La idea es bastante simple: quiero separar los registros en grupo (30 días), en qué grupo está el registro más pequeño
new
, los demás lo estánfollow ups
. Verifique cómo se construye la declaración:Entonces:
* 1.0 / 30
se agrega+ 0.000001
; Además, estamos utilizando la función de techo para obtener elsmallest integer greater than, or equal to, the specified numeric expression
Eso es. Teniendo dicho grupo simplemente usamos
ROW_NUMBER
para encontrar nuestra fecha de inicio y que sea lonew
y dejando el resto comofollow ups
.fuente
Con el debido respeto a todos y en mi humilde opinión,
No hay mucho aumento de rendimiento cuando se usa
Recursive CTE
yWindow Partition function
todo en uno.Appid
debería serint identity(1,1)
, o debería estar aumentando cada vez másclustered index
.Además de otros beneficios, también asegura que todas las filas sucesivas
APPDate
de ese paciente deben ser mayores.De esta manera, puede jugar fácilmente
APPID
en su consulta, que será más eficiente que ponerinequality
operador como>, <en APPDate. Poner alinequality
operador como>, <en APPID ayudará a Sql Optimizer.También debe haber dos columnas de fecha en la tabla como
Como estas son las columnas más importantes en la tabla más importante, entonces no hay mucho reparto, conversión.
Entonces
Non clustered index
se puede crear en AppdatePruebe mi script con otros datos de muestra y déjeme saber para qué datos de muestra no funciona. Incluso si no funciona, estoy seguro de que puede solucionarse en la lógica de mi script.
fuente
Aunque no se trata con claridad en la pregunta, es fácil darse cuenta de que las fechas de las citas no se pueden clasificar simplemente por grupos de 30 días. No tiene sentido comercial. Y tampoco puedes usar el id de appt. Uno puede hacer una nueva cita hoy para
2020-09-06
. Así es como abordo este problema. Primero, obtenga la primera cita, luego calcule la diferencia de fecha entre cada cita y la primera cita. Si es 0, configúrelo en 'Nuevo'. Si <= 30 'Seguimiento'. Si> 30, configúrelo como 'Indeciso' y realice la siguiente ronda de verificación hasta que no haya más 'Indeciso'. Y para eso, realmente necesita un ciclo while, pero no recorre cada fecha de cita, sino solo unos pocos conjuntos de datos. Revisé el plan de ejecución. A pesar de que solo hay 10 filas, el costo de la consulta es significativamente menor que el uso de CTE recursivo, pero no tan bajo como el método de apéndice de Lukasz Szozda.fuente
Espero que esto ayude.
fuente
Podrías usar una
Case
declaración .La pregunta es, ¿debería asignarse esta categoría según la cita inicial o la anterior? Es decir, si un paciente ha tenido tres citas, ¿deberíamos comparar la tercera cita con la primera o la segunda?
Tu problema es el primero, que es como he respondido. Si ese no es el caso, querrás usarlo
lag
.Además, tenga en cuenta que
DateDiff
no es una excepción para los fines de semana. Si esto fuera solo de lunes a viernes, deberá crear su propia función de valor escalar.fuente
usando la función Lag
Demostración -> https://rextester.com/TNW43808
fuente
apptDate
como laorder by
columna de lalag
función (lo que realmente debería como id no es garantía de nada), aún puede romperse fácilmente al introducir más citas de seguimiento. Vea esta demostración de Rextester por ejemplo. Buen intento, sin embargo ...New
y no unFollowUp
. Han pasado más de 30 días desde la primera cita de ese paciente ... Debería contar 30 días desde cadaNew
cita y luego usar unaNew
vez más ...La mía es correcta. Los autores fueron incorrectos, ver transcurrido
fuente