MySQL SELECT ONDE datetime corresponde ao dia (e não necessariamente ao horário)

127

Eu tenho uma tabela que contém uma coluna datetime. Desejo retornar todos os registros de um determinado dia, independentemente da hora. Ou, em outras palavras, se minha tabela contiver apenas os 4 registros a seguir, somente o 2º e o 3º serão retornados se eu limitar a 2012-12-25.

2012-12-24 00:00:00
2012-12-25 00:00:00
2012-12-25 06:00:00
2012-12-26 05:00:00
user1032531
fonte
Veja a resposta de John Woo no stackoverflow.com/questions/14769026/…
ekerner

Respostas:

326

NUNCA use um seletor como DATE(datecolumns) = '2012-12-24'esse - é um ótimo desempenho:

  • calculará DATE()para todas as linhas, incluindo aquelas que não correspondem
  • tornará impossível usar um índice para a consulta

É muito mais rápido usar

SELECT * FROM tablename 
WHERE columname BETWEEN '2012-12-25 00:00:00' AND '2012-12-25 23:59:59'

pois isso permitirá o uso do índice sem cálculo.

EDITAR

Como apontado por Used_By_Already, desde a resposta inicial em 2012, surgiram versões do MySQL, nas quais usar '23: 59: 59 'como final do dia não é mais seguro. Uma versão atualizada deve ler

SELECT * FROM tablename 
WHERE columname >='2012-12-25 00:00:00'
AND columname <'2012-12-26 00:00:00'

A essência da resposta, ou seja, evitar um seletor em uma expressão calculada, é claro, ainda permanece.

Eugen Rieck
fonte
Eu estava prestes a comentar que a solução do a1ex07 não parece tão boa quanto as outras. Depois de ler sua postagem, talvez eu precise reverter o meu pensamento!
user1032531
2
Apenas testado em dois servidores, o acima é MUITO (pelo menos 10x) mais rápido que date () = '', especialmente para tabelas enormes. Graças
ZZAPPER
1
@KonradViltersten Eu usei uma maneira muito detalhada de formular a consulta para torná-la mais legível e levar para casa o meu ponto, sem refiná-lo. A resposta de a1ex07 tem a sintaxe esparsa.
21814 Eugen Rieck
9
@KonradViltersten - Melhor ainda: WHERE col >= '2012-12-25' AND col < '2012-12-25' + INTERVAL 1 DAY. Evita 0 tempo e trabalha para DATE, DATETIME, DATETIME(6), etc. e lida com salto-dia, etc.
Rick James
1
'2012-12-25 23:59:59' NÃO É VÁLIDO como um final de dia, sempre foi uma má ideia e causará bugs nas versões do MySQL que suportam precisão de tempo de menos de um segundo. É muito melhor usar a abordagem de Rick James (acima) ou a1ex07 (outra resposta) #
12336 Used_By_Already
34

... WHERE date_column >='2012-12-25' AND date_column <'2012-12-26'potencialmente pode funcionar melhor (se você tiver um índice em date_column) que DATE.

a1ex07
fonte
1
Na verdade, eu me pergunto o que é mais rápido - essa ou a BETWEENsolução ... alguém foi marcado?
jave.web
6
Não deve haver nenhuma diferença. BETWEENé apenas uma maneira de escrever field >= value1 and fied<= value2.
a1ex07
1
Observe que, de acordo com o MySQL Manual: "Para obter melhores resultados ao usar BETWEEN com valores de data ou hora, use CAST () para converter explicitamente os valores no tipo de dados desejado. Exemplos: Se você comparar um DATETIME a dois valores de DATE, converta o DATE valores para valores DATETIME. Se você usar uma constante de seqüência de caracteres como '2001-1-1' em uma comparação com um DATE, transmita a seqüência para um DATE. " Portanto, a menos que sejam todos do mesmo tipo, é melhor convertê-los explicitamente.
techdude
21

Você pode usar %:

SELECT * FROM datetable WHERE datecol LIKE '2012-12-25%'
Ghilas BELHADJ
fonte
13
LIKE parece ser tão lento quanto DATE (datetimecol). Melhor usar a solução de Eugen ou a1ex07.
Marie Fischer
3
Nem sempre é sobre velocidade. Então, eu gosto desta solução. É muito mais legível.
Simon Hansen