O servidor de mesa da Oracle oferece uma função integrada TRUNC(timestamp,'DY')
,. Esta função converte qualquer carimbo de data / hora em meia-noite do domingo anterior. Qual é a melhor maneira de fazer isso no MySQL?
A Oracle também oferece TRUNC(timestamp,'MM')
a conversão de um carimbo de data / hora em meia-noite do primeiro dia do mês em que ocorre. No MySQL, este é direto:
TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))
Mas esse DATE_FORMAT
truque não funcionará por semanas. Estou ciente da WEEK(timestamp)
função, mas realmente não quero o número da semana dentro do ano; esse material é para trabalho de vários anos.
TRUNC(date, 'DY' )
obtém semanas com início no domingo.'W'
começa uma segunda-feira, pelo menos no meu sistema.Respostas:
Você pode usar ambos
YEAR(timestamp)
eWEEK(timestamp)
, e usar ambas as estas expressões naSELECT
eaGROUP BY
cláusula.Não excessivamente elegante, mas funcional ...
E, claro, você pode combinar essas duas partes de data em uma única expressão também, ou seja, algo como
SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc... FROM ... WHERE .. GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))
Edit : Como Martin aponta, você também pode usar a
YEARWEEK(mysqldatefield)
função, embora sua saída não seja tão amigável quanto a fórmula mais longa acima.Editar 2 [3 1/2 anos depois!]:
YEARWEEK(mysqldatefield)
Com o segundo argumento opcional (mode
) definido como 0 ou 2 é provavelmente a melhor maneira de agregar por semanas completas (ou seja, incluindo semanas que duram mais de 1º de janeiro), se for o que é desejado. AYEAR() / WEEK()
abordagem proposta inicialmente nesta resposta tem o efeito de dividir os dados agregados para essas semanas "abrangentes" em duas: uma com o ano anterior e outra com o ano novo.Um corte limpo todo ano, ao custo de ter até duas semanas parciais, uma em cada extremidade, é frequentemente desejado na contabilidade, etc. e para isso a
YEAR() / WEEK()
abordagem é melhor.fonte
YEARWEEK()
resulta em umINT(6)
que acredito será mais rápido para classificar / ingressar / agrupar comA resposta aceita acima não funcionou para mim, porque ordenou as semanas por ordem alfabética, não cronológica:
Esta é minha solução para contar e agrupar por semana:
SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, YEAR(date), WEEK(date), COUNT(*) FROM column_name GROUP BY week_name ORDER BY YEAR(DATE) ASC, WEEK(date) ASC
Gera:
fonte
ORDER BY date ASC
) deve funcionar tambémDescobri ... é um pouco complicado, mas aqui está.
E, se suas regras de negócios dizem que suas semanas começam às segundas-feiras, altere
-1
para-2
.Editar
Anos se passaram e eu finalmente consegui escrever isso. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
fonte
Você pode obter o ano concatenado e o número da semana (200945) usando a função YEARWEEK () . Se eu entendi sua meta corretamente, isso deve permitir que você agrupe seus dados plurianuais.
Se você precisa do timestamp real para o início da semana, é menos agradável:
Para ordenação mensal, você pode considerar a função LAST_DAY () - ordenar seria pelo último dia do mês, mas isso deveria ser equivalente a ordenar pelo primeiro dia do mês ... não deveria?
fonte
Basta adicionar isso no select:
E
fonte
Se você precisar da data de "término da semana", isso também funcionará. Isso contará o número de registros para cada semana. Exemplo: Se três ordens de serviço foram criadas entre (inclusive) 1/2/2010 e 1/8/2010 e 5 foram criadas entre (inclusive) 1/9/2010 e 1/16/2010, isso retornaria:
3 1/8/2010
5 1/16/2010
Tive que usar a função DATE () extra para truncar meu campo de data e hora.
SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending FROM work_order wo GROUP BY week_ending;
fonte