Temos tabela de compromissos, como mostrado abaixo. Cada compromisso precisa ser categorizado como "Novo" ou "Acompanhamento". Qualquer consulta (para um paciente) dentro de 30 dias da primeira consulta (desse paciente) é Acompanhamento. Após 30 dias, a nomeação é novamente "Nova". Qualquer compromisso dentro de 30 dias se torna "Acompanhamento".
Atualmente, estou fazendo isso digitando while loop.
Como conseguir isso sem o loop WHILE?
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 provavelmente seja sua melhor opção, em termos de desempenho.Respostas:
Você precisa usar a consulta recursiva.
O período de 30 dias é contado a partir de anterior (e não, não é possível fazê-lo sem recursão / atualização / loop peculiar). É por isso que toda a resposta existente usando apenas
ROW_NUMBER
falhou.db <> demo de violino
Resultado:
Como funciona:
Classe semelhante:
Soma Condicional no Oracle - Limpando uma Função de Janela
Janela de sessão (Azure Stream Analytics)
Total em execução até que a condição específica seja verdadeira - Atualização peculiar
Termo aditivo
Nunca use esse código na produção!
Isso poderia ser feito na rodada "única" (atualização peculiar):
Inquerir:
atualização quirky do violino do db <>
fonte
RANGE x PRECEDING
cláusula.Você poderia fazer isso com um cte recursivo. Você deve primeiro solicitar por apptDate em cada paciente. Isso pode ser conseguido por meio de um CTE comum.
Em seguida, na parte âncora do seu recursivo, selecione a primeira ordem para cada paciente, marque o status como 'novo' e marque apptDate como a data do 'novo' registro mais recente.
Na parte recursiva do cte recursivo, aumente para o próximo compromisso, calcule a diferença de dias entre o presente e a mais recente data do novo compromisso. Se for superior a 30 dias, marque-o como 'novo' e redefina a data do novo compromisso mais recente. Caso contrário, marque-o como "acompanhamento" e passe apenas os dias existentes desde a nova data do compromisso.
Por fim, na consulta base, basta selecionar as colunas que deseja.
Devo mencionar que, inicialmente, excluí esta resposta porque a resposta de Abhijeet Khandagale parecia atender às suas necessidades com uma consulta mais simples (depois de reformulá-la um pouco). Mas, com seu comentário sobre seus requisitos de negócios e seus dados de amostra adicionados, cancelei a exclusão dos meus porque acredito que este atenda às suas necessidades.
fonte
Não tenho certeza de que é exatamente o que você implementou. Mas outra opção, que vale a pena mencionar, além de usar o cte, é usar a tabela temporária e atualizar em "rodadas". Então, vamos atualizar a tabela temporária enquanto todos os status não estiverem definidos corretamente e criar o resultado de maneira iterativa. Podemos controlar o número de iterações usando simplesmente variáveis locais.
Então, dividimos cada iteração em dois estágios.
assim
Atualizar. Leia o comentário fornecido por Lukasz. É de maneira muito mais inteligente. Deixo minha resposta apenas como uma ideia.
fonte
Acredito que a expressão comum recursiva é uma ótima maneira de otimizar consultas, evitando loops, mas em alguns casos pode levar a um desempenho ruim e deve ser evitada, se possível.
Uso o código abaixo para resolver o problema e testá-lo com mais valores, mas encorajo você a testá-lo com seus dados reais também.
A ideia é bem simples - quero separar os registros em grupo (30 dias), em qual grupo o menor é o registro
new
e os outrosfollow ups
. Verifique como a declaração é criada:Assim:
* 1.0 / 30
é adicionado+ 0.000001
; Além disso, estamos usando a função de teto para obter osmallest integer greater than, or equal to, the specified numeric expression
É isso aí. Tendo esse grupo, simplesmente usamos
ROW_NUMBER
para encontrar nossa data de início e torná-la comonew
e deixando o resto comofollow ups
.fonte
Com o devido respeito a todos e no IMHO,
Não há muito ganho de desempenho ao usar
Recursive CTE
eWindow Partition function
tudo em um.Appid
deveria serint identity(1,1)
, ou deveria estar sempre aumentandoclustered index
.Além de outros benefícios, também garante que todas as filas sucessivas
APPDate
desse paciente sejam maiores.Dessa forma, você pode facilmente brincar com
APPID
sua consulta, o que será mais eficiente do que colocar oinequality
operador como>, <em APPDate. Colocar oinequality
operador como>, <no APPID ajudará o Sql Optimizer.Também deve haver duas colunas de data na tabela como
Como essas são as colunas mais importantes da tabela mais importante, então não muito elenco, converta.
Então
Non clustered index
pode ser criado no AppdateTeste meu script com outros dados de amostra e deixe-me saber para quais dados de amostra ele não está funcionando. Mesmo que não funcione, tenho certeza de que pode ser corrigido na minha própria lógica de script.
fonte
Embora não esteja claramente abordado na pergunta, é fácil descobrir que as datas dos compromissos não podem ser simplesmente categorizadas por grupos de 30 dias. Não faz sentido nos negócios. E você também não pode usar o ID do agendamento. Pode-se marcar uma nova consulta hoje para
2020-09-06
. Aqui está como eu resolvo esse problema. Primeiro, obtenha o primeiro compromisso e calcule a diferença de data entre cada compromisso e o primeiro agendamento. Se for 0, defina como 'Novo'. Se <= 30 'Acompanhamento'. Se> 30, defina como 'Indeciso' e faça a próxima rodada até que não haja mais 'Indeciso'. E para isso, você realmente precisa de um loop while, mas ele não percorre a data de cada compromisso, apenas alguns conjuntos de dados. Eu verifiquei o plano de execução. Embora existam apenas 10 linhas, o custo da consulta é significativamente menor que o do CTE recursivo, mas não tão baixo quanto o método de adendo de Lukasz Szozda.fonte
Eu espero que isso te ajude.
fonte
Você poderia usar uma
Case
declaração .A questão é: essa categoria deve ser atribuída com base no compromisso inicial ou no anterior? Ou seja, se um paciente teve três consultas, devemos comparar a terceira consulta com a primeira ou a segunda?
Seu problema declara o primeiro, e foi assim que eu respondi. Se não for esse o caso, convém usar
lag
.Além disso, lembre-se de que isso
DateDiff
não é exceção nos finais de semana. Se for apenas durante a semana, você precisará criar sua própria função com valor escalar.fonte
usando a função Lag
Demonstração -> https://rextester.com/TNW43808
fonte
apptDate
como aorder by
coluna dalag
função (que você realmente deve como id não é garantia de nada), ela ainda poderá ser quebrada facilmente, introduzindo mais compromissos de acompanhamento. Veja esta demonstração do Rextester, por exemplo. Boa tentativa, embora ...New
e não umFollowUp
. Faz mais de 30 dias desde a primeira consulta desse paciente ... Você deve contar 30 dias desde cadaNew
consulta e depois usarNew
novamente ...O meu está correto. Os autores estavam incorretos.
fonte