Estou ajustando uma consulta no SQL Server 2012 que está vazando para tempdb devido a uma estimativa de cardinalidade incorreta ao usar a DATENAME()
função em uma coluna para verificar se os dados são de fim de semana ou dia da semana. Devido ao uso da função, a consulta não pode ser sargável e estima incorretamente o número de linhas (est 1700, real 38000).
A cláusula where era simplesmente:
WHERE DATENAME(WEEKDAY, vqc.DateRecorded) NOT IN ('Saturday', 'Sunday')
Eu esperava usar uma coluna computada persistente e, em seguida, indexá-la:
ALTER TABLE <table_name> ADD IsWeekend AS DATENAME(WeekDay, DateRecorded) PERSISTED;
No entanto, obtenha o erro:
A coluna calculada 'IsWeekend' na tabela não pode ser mantida porque a coluna não é determinística.
De acordo com BOL , um grande número de funções Date não pode ser persistido porque elas não são determinísticas.
Isso ocorre porque os resultados dependem das configurações LANGUAGE e DATEFORMAT da sessão do servidor. Por exemplo, os resultados da expressão CONVERT (datetime, '30 listopad 1996', 113) dependem da configuração LANGUAGE porque a string '30 listopad 1996' significa meses diferentes em idiomas diferentes. Da mesma forma, na expressão DATEADD(mm,3,'2000-12-01'), o Mecanismo de Banco de Dados interpreta a string '2000-12-01' com base na configuração DATEFORMAT.
Havia uma maneira interessante de contornar esse problema para a MONTH()
função usando uma CASE
instrução que foi postada no Stack Overflow , mas isso não funciona DATENAME
devido a SET DATEFIRST
e à LANGUAGE
configuração.
Além de ingressar em uma tabela de calendário em minha consulta e, em seguida, filtrar os fins de semana a partir daí, existe uma maneira de determinar se uma data é o fim de semana para que possa ser mantida e indexada?
Ou estou tentando complicar demais a situação?
Você pode fazer um
datediff
between1900-01-01
, que por acaso é uma segunda-feira, e verificar se modulo7
é a5
ou a6
.BTW, você não precisa persistir na coluna computada para usá-la em um índice.