Como você armazena "datas difusas" em um banco de dados?

125

Este é um problema que já encontrei algumas vezes. Imagine que você tem um registro que deseja armazenar em uma tabela de banco de dados. Esta tabela possui uma coluna DateTime chamada "date_created". Esse registro em particular foi criado há muito tempo e você não tem certeza da data exata, mas sabe o ano e o mês. Outros registros que você conhece apenas o ano. Outros registros que você conhece o dia, mês e ano.

Você não pode usar um campo DateTime, porque "maio de 1978" não é uma data válida. Se você o dividir em várias colunas, perderá a capacidade de consultar. Alguém mais se deparou com isso? Em caso afirmativo, como você lidou com isso?

Para esclarecer o sistema que estou construindo, é um sistema que rastreia arquivos. Algum conteúdo foi produzido há muito tempo, e tudo o que sabemos é "maio de 1978". Eu poderia armazená-lo em 1º de maio de 1978, mas apenas com alguma maneira de indicar que essa data é precisa apenas para o mês. Dessa forma, alguns anos depois, quando estou recuperando esse arquivo, não fico confuso quando as datas não coincidem.

Para meus propósitos, é importante diferenciar "dia desconhecido em maio de 1978" com "1º de maio de 1978". Além disso, eu não gostaria de armazenar as incógnitas como 0, como "0 de maio de 1978", porque a maioria dos sistemas de banco de dados rejeitará isso como um valor de data inválido.

nbv4
fonte
14
É importante diferenciar "dia desconhecido em maio de 1978" com "1º de maio de 1978"?
5
@ MichaelT: sim, é importante diferenciar.
Nbv4
6
@aslum: A maioria dos sistemas de banco de dados irá rejeitar isso como um valor de data inválido
nbv4
9
@ JimmyHoffa - você nunca se deparou com um cenário de datas confusas ou em um cenário em que precisava comparar datas? Em ambos os casos, uma comum é uma história médica: você se lembra que a apendicectomia foi no ano passado em 1º de abril, mas a amigdalectomia ocorreu em 1975, e outra coisa aconteceu durante maio e junho de um ano. E se você quiser saber se algum evento médico ocorreu antes ou depois de outro avanço médico? Isso aconteceu antes ou depois da verificação do suprimento de sangue para o HIV?
thursdaysgeek

Respostas:

148

Armazene todas as datas no campo DATE normal no banco de dados e tenha um campo de precisão adicional com a precisão do campo DATE.

date_created DATE,
date_created_accuracy INTEGER, 

date_created_accuracy: 1 = data exata, 2 = mês, 3 = ano.

Se a sua data for imprecisa (por exemplo, maio de 1980), armazene-a no início do período (por exemplo, 1º de maio de 1980). Ou se sua data for precisa para o ano (por exemplo, 1980), armazene-a como 1º de janeiro. 1980 com o valor de precisão correspondente.

Dessa maneira, é possível consultar facilmente de uma maneira um tanto natural e ainda ter noção de como as datas são precisas. Por exemplo, isso permite consultar datas entre Jan 1st 1980e Feb 28th 1981, e obter datas difusas 1980e May 1980.

Juha Syrjälä
fonte
1
Você ainda precisa calcular o final da data aqui, pelo que posso ver, por isso acho que a consulta intermediária é bastante feia, pois você tem um campo calculado que está selecionando na melhor das hipóteses.
Wyatt Barnett
8
Boa resposta, muito inteligente. select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;. Gênio.
Naftuli Kay
58
Recomendamos que você considere a precisão da data como simplesmente "dias". Onde um dia exato é 0. Dessa forma, é possível usar datas mais flexíveis "Algum dia no verão", com uma precisão de data de 90 dias com base em 1º de junho, em vez de períodos específicos codificados. Ele também pode lidar com precisão de vários anos.
1
Você deve talvez alegam que como uma resposta, MichaelT
Supr
1
+1: Outra coisa interessante dessa solução é que você pode adicionar a lógica de exibição com base no valor do date_created_accuracycampo. Você pode mostrar "maio de 1980" ou apenas "1980" nos resultados ou na interface do usuário se isso for tão preciso quanto o campo indica.
26815 Kyralessa
27

Se você não precisar usar esse tipo de dados como informações regulares de data e hora, qualquer formato simples de string seria necessário.

Mas se você precisar manter toda a funcionalidade, existem duas soluções alternativas que podem ser consideradas, ambas exigindo informações adicionais armazenadas no banco de dados:

  1. Crie min datee max datecampos, que tenham valores diferentes para dados "incompletos", mas coincidam com datas precisas.
  2. Crie tipos para cada tipo de data imprecisa (nenhuma _ 0, data_aproximação _ 1, mês_aproximação _2, ano_aproximação_4, etc _ para que você possa combiná-las). Adicione um typecampo aos registros e mantenha as informações ausentes.
superM
fonte
Os campos de data mínima e máxima também foram o meu primeiro pensamento.
Michael Itzoe
1
Há muito tempo, tivemos que resolver exatamente o mesmo problema. Os usuários podiam contar histórias sobre eventos que aconteceram a qualquer momento no passado, então tivemos que oferecer suporte a datas confusas. Depois de muitas idas e vindas, a solução que chegamos é mais semelhante à sugestão de superM aqui, onde as datas são armazenadas como o mínimo e o máximo possível de instantes que conteriam a data da história. Ao relatar a data, a precisão (ou seja, "esse registro é preciso até o mês / ano / dia") pode ser extraída do delta entre as datas mín. E máx. Não há necessidade de armazenar um terceiro campo para precisão.
Meetamit
4
+1 para min datee max datecampos. Eu acho que é a solução mais flexível, precisa e fácil de usar.
Supr
1
Eu era antagônico a essa ideia no começo. Mas, percebendo que é a abordagem mais flexível, voto a favor.
Anurag Kalia 9/04
É natural. Você está descrevendo não tanto uma data confusa, mas um período de tempo ..... que tem um começo e um fim.
Pieter B
20

Isso é realmente mais uma definição de requisitos do que um problema técnico - o que você precisa focar é "como podemos definir as datas no passado" e a solução técnica fluirá.

Nas vezes em que tive que abordar algo assim, normalmente:

  • Defina como mapear as coisas - como sugere MichaelT , decida que tudo o que for definido como Mês / Dia será definido como meia-noite no primeiro dia do referido mês. Isso normalmente é bom o suficiente para a maioria dos propósitos - se a data exata fosse tão importante, você provavelmente teria um registro dela 35 anos depois, certo?
  • Descobrir se você precisa acompanhar isso - ou seja, os registros com datas de criação levemente inventadas precisam de uma bandeira dizendo isso? Ou isso é apenas uma questão de treinamento do usuário para que as pessoas saibam e possam agir de acordo.

Às vezes, é necessário fazer algo como tornar as datas imprecisas - por exemplo, essa data pode precisar responder a uma consulta em maio de 1978. Isso é possível - basta fazer seus campos create_date 2, registros antigos obtêm 30 dias, conforme apropriado, os novos obtêm 2 valores idênticos.

Wyatt Barnett
fonte
1
+1 - Eu estava trabalhando na formulação de uma resposta com a abordagem de data dupla. Sua resposta chegou aqui primeiro.
2
+1, é feio e cria muitas informações extras inúteis para as novas entradas que não exigem, mas, por outro lado, mantém as consultas muito mais simples do que seriam. Estamos usando uma solução semelhante para um problema relacionado há um tempo.
Izkata
3
@ Izkata - Ponto justo, mas quão elegante você pode ficar quando precisa criar algo que deve ser um ponto único no período de um mês. Certamente mais bonito do que ter que calcular o início e o fim de consultas em tempo real em algum lugar.
Wyatt Barnett
1
+1 por poder denotar granularidade arbitrária sem uma explosão de valores enum.
9113 Dan Neely
18

A maneira mais simples de indicar se a data é precisa é criar um campo de precisão INT (1) com NULL padrão

Se a data for exata, armazene a data e a hora em "date_created" e deixe a precisão NULL

Se a data for precisa apenas para armazenar a data e hora do mês como 1º do mês com valor de precisão 1

Se a data for precisa apenas para a data do ano da loja, data de 1º de janeiro com o valor de precisão 2

Você pode usar números diferentes para armazenar valores diferentes, como primeiro trimestre, etc.

david strachan
fonte
As consultas ficam realmente difíceis quando você faz isso.
Blrfl
3
Isso tem dificuldade com dados que não estão em um limite de mês limpo, como "Q2 1991" e "Winter 1978-1979".
1
O OP quer uma maneira de indicar que essa data é precisa apenas para o mês.
David strachan
7
Você está abusando do significado de NULL aqui. NULL significa "desconhecido", portanto, se a data for precisa, a precisão não poderá ser NULL. Pode ser '1'.
Konerak
@ Konerak Semanticamente sim. Mas como a maioria das datas é precisa, apenas os casos especiais precisam ser identificados e usando NULL aqui como padrão.
David strachan
17

No passado, eu armazenava datas com precisão como uma data de início e uma data de término. O dia 21 de maio de 2012 seria representado como início = 12 horas, maio 21,2012 e final = 12 horas, 22 de maio de 2012. O ano de 2012 seria representado como início = 12 horas, jan1,2012 final = 12 horas, jan1,2013.

Não tenho certeza se eu recomendaria essa abordagem. Ao exibir as informações para o usuário, você precisa detectar adequadamente que um período cobre exatamente um dia para mostrar "25 de maio" em vez de dois pontos de extremidade excessivamente específicos (o que significa lidar com o horário de verão e assim por diante).

No entanto, quando você não está tentando traduzir para humanos, programar com os pontos de extremidade é muito mais fácil do que com a precisão central +. Você não acaba com muitos casos. Isso é muito legal.

Craig Gidney
fonte
Na verdade, não precisa ser tão complicado determinar como apresentar um intervalo, se o intervalo for sempre armazenado como UTC. Como carimbos de data e hora UTC, todos os dias, semanas, meses, anos - inclusive estações e trimestres - terão dois números constantes, globais, distintos e facilmente determináveis, representando o início e o fim do período. A lógica simplesmente se torna algumas declarações if para ver se as duas datas estão no início e no final de algum tipo de período. Não são necessárias coisas complicadas de matemática ou fuso horário :) #
09/04 supra
@Supr Determinar se um determinado segundo está na fronteira de um determinado período humano é, por si só, um problema difícil. Especialmente a longo prazo, com a rotação da Terra diminuindo e intermináveis ​​pequenas mudanças na definição humana de hora local.
Craig Gidney
14

Por que não armazenar duas datas.

Created_After e Created_Before. A semântica real sendo "criada em ou depois" e "criada em ou antes"

Portanto, se você souber a data exata, Created_After e Created_Before serão a mesma data.

Se você souber que foi a primeira semana de maio de 2000, Created_After = '2000-05-01' e Created_Before = '2000-05-07'.

Se você conhece maio de 1999, os valores serão '1999-05-01' e '1999-05-30'.

Se for "verão de 42", os valores serão '1942-06-01' e '1942-08-31'.

Esse esquema é simples de consultar com SQL normal e bastante fácil para um usuário não técnico seguir.

Por exemplo, para encontrar todos os documentos que podem ter sido criados em maio de 2001:

SELECT * FROM DOCTAB WHERE Created_After < '2001-05-31' And Created_Before > 2001-05-01;

Por outro lado, para encontrar todos os documentos que foram definitivamente criados em maio de 2001:

SELECT * FROM DOCTAB WHERE Created_After > '2001-05-01' And Created_Before < 2001-05-31;
James Anderson
fonte
1
Eu acho que essa é a solução mais elegante.
21413 Pieter B
É o mesmo que as respostas da superM e da Strilanc. +1, no entanto, para explicar com mais clareza e mostrar como seria simples consultar.
Supr
9

O formato de data e hora ISO 8601 é fornecido com definição de duração, por exemplo

2012-01-01P1M (leia-se: 2012, 1º de janeiro, período: 1 mês) é o que deve ser “em janeiro de 2012”.

Eu usaria isso para armazenar os dados. Você pode precisar de um campo de banco de dados do tipo String para fazer isso. É um tópico diferente sobre como realizar uma pesquisa sensata sobre isso.

Matthias Ronge
fonte
+1 para a idéia, mas -1 para não usar um campo de data para a razão como procurar e / ou encontrar
user151019
Depende do banco de dados. No entanto, isso pode ser a base da expansão, mas a questão é: o documento está no conjunto de resultados se você pesquisar, nesse caso, todos os documentos mais recentes que o dia 12 de janeiro, ou não? Não é trivial. Aqui, a questão era como armazenar datas confusas.
Matthias Ronge
3

Geralmente, eu ainda as armazeno, pois as datas para o uso geral de consultas ainda são possíveis, mesmo que um pouco menos precisas.

Se é importante saber a precisão que eu tinha no passado, armazenou uma "janela" de precisão como um decimal +/- ou como uma pesquisa (dia, mês, ano etc.). Noutros casos, em vez da janela, guardo o valor da data original como uma cadeia e converto o que posso para uma data e hora, possivelmente 1978-05-01 00:00:00 e "maio de 1978" para o seu exemplo.

Conta
fonte
3

Se você o dividir em várias colunas, perderá a capacidade de consultar.

Quem disse? Aqui está o que você faz:

  1. Tenha 3 colunas, Dia, Mês, Ano, cada um do tipo int, e uma quarta coluna, TheDate, do tipo DateTime.
  2. Tenha um gatilho que use as 3 colunas Dia, Mês, Ano para criar TheDate se TheDate for deixado nulo, mas um ou mais dos campos Dia, Mês e Ano tiverem um valor.
  3. Tenha um gatilho que preencha os campos Dia, Mês e Ano quando TheDate for fornecido, mas esses campos não.

Portanto, se eu fizer uma inserção como: o insert into thistable (Day, Month, Year) values (-1, 2, 2012);TheDate se tornará 01/02/2013, mas saberei que é realmente uma data indeterminada em 2/2012 por causa do -1 no campo Dia.

Se insert into thistable (TheDate) values ('2/5/2012');então o dia for 5, o mês será 2 e o ano será 2012 e, como nenhum deles é -1, saberei que esta é a data exata.

Não perco a capacidade de consultar porque o gatilho de inserção / atualização garante que meus 3 campos (dia, mês, ano) sempre produzam um valor DateTime em TheDate que pode ser consultado.

lixo
fonte
3

Outra opção seria armazenar as datas como números inteiros do formulário YYYYMMDD.

  • Você só sabe que o ano é 1951: Store as 19510000
  • Você sabe que o mês e o ano são março de 1951: 19510300
  • Você sabe que a data completa é 14 de março de 1951: 19510314
  • Uma data completamente desconhecida: armazenar como 0

Benefícios

Você pode armazenar sua data difusa em um campo em vez de dois campos de data ou uma data e uma precisão, conforme sugerem muitas das outras respostas.

As consultas ainda são fáceis:

  • todos os registros para o ano de 1951 - SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
  • todos os registros de março de 1951 - SELECT * FROM table where thedate>=19510300 and thedate<19510400
  • todos os registros de 14 de março de 1951 - SELECT * FROM table where thedate=19510314

NOTAS

  • Sua GUI precisaria de uma GetDateString(int fuzzyDate)que seja bastante fácil de implementar.
  • A classificação é fácil com o formato int. Você deve saber que datas desconhecidas virão primeiro. Você pode reverter isso usando 99o 'preenchimento' em vez do 00mês ou dia.
Rick
fonte
Como você representa a data nebulosa do "inverno de 1941-1942"? Pode ser em dezembro de 1941 ou em janeiro de 1942.
1
Sua pergunta está relacionada a um caso de solução geral. A pergunta original não lista isso como um problema. Com base na pergunta postada, às vezes a data completa é conhecida, às vezes apenas o ano e o mês, e às vezes apenas o ano. Nenhum problema de um período difuso é mencionado como requisito. Concordo que você precisará de duas datas se precisar resolver esse problema (embora armazenar o intervalo como duas "entradas de data fuzzy" possa fornecer mais flexibilidade do que armazenar duas datas "difíceis").
Rick
1

A ISO 8601 também especifica uma sintaxe para "datas difusas". 12 de fevereiro de 2012 às 15:00 seria "2012-02-12T15" e fevereiro de 2012 poderia ser simplesmente "2012-02". Isso se estende muito bem usando a classificação lexicográfica padrão:

$ (echo "2013-03"; echo "2013-03"; echo "2012-02-12T15"; echo "2012-02"; echo "2011") | sort
2011
2012
2012-02
2012-02-12T15
2013-03
Uma resposta
fonte
0

Aqui está a minha opinião sobre isso:

Vá da data difusa para o objeto datetime (que caberá em um banco de dados)

import datetime
import iso8601

def fuzzy_to_datetime(fuzzy):
    flen = len(fuzzy)
    if flen == 4 and fuzzy.isdigit():
        dt = datetime.datetime(year=int(fuzzy), month=1, day=1, microsecond=111111)

    elif flen == 7:
        y, m = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=1, microsecond=222222)

    elif flen == 10:
        y, m, d = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=int(d), microsecond=333333)

    elif flen >= 19:
        dt = iso8601.parse_date(fuzzy)

    else:
        raise ValueError("Unable to parse fuzzy date: %s" % fuzzy)

    return dt

E então uma função que pega o objeto datetime e o move de volta para uma data difusa.

def datetime_to_fuzzy(dt):
    ms = str(dt.microsecond)
    flag1 = ms == '111111'
    flag2 = ms == '222222'
    flag3 = ms == '333333'

    is_first = dt.day == 1
    is_jan1 = dt.month == 1 and is_first

    if flag1 and is_jan1:
        return str(dt.year)

    if flag2 and is_first:
        return dt.strftime("%Y-%m")

    if flag3:
        return dt.strftime("%Y-%m-%d")

    return dt.isoformat()

E depois um teste de unidade. Perdi alguns casos?

if __name__ == '__main__':
    assert fuzzy_to_datetime('2001').isoformat() == '2001-01-01T00:00:00.111111'
    assert fuzzy_to_datetime('1981-05').isoformat() == '1981-05-01T00:00:00.222222'
    assert fuzzy_to_datetime('2012-02-04').isoformat() == '2012-02-04T00:00:00.333333'
    assert fuzzy_to_datetime('2010-11-11T03:12:03Z').isoformat() == '2010-11-11T03:12:03+00:00'

    exact = datetime.datetime(year=2001, month=1, day=1, microsecond=231)
    assert datetime_to_fuzzy(exact) == exact.isoformat()

    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=1, day=1, microsecond=111111)) == '2001'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=3, day=1, microsecond=222222)) == '2001-03'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=6, day=6, microsecond=333333)) == '2001-06-06'

    assert datetime_to_fuzzy(fuzzy_to_datetime('2002')) == '2002'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-05')) == '2002-05'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-02-13')) == '2002-02-13'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2010-11-11T03:12:03.293856+00:00')) == '2010-11-11T03:12:03.293856+00:00'

Há um caso de canto em que um evento que ocorreu precisamente, 2001-01-01T00:00:00.333333mas o sistema interpretará como sendo apenas "2001", mas isso parece muito improvável.

nbv4
fonte
0

Eu trabalho para uma editora que lida com muitos livros antigos, onde geralmente não conseguimos as datas exatas para isso. Nós normalmente têm dois campos para uma determinada entrada de data, a data e um circa boolean:

date date
dateCirca enum('Y', 'N')

Usamos o campo de data para indicar a data de algum evento ou uma data "suficientemente próxima" no caso em que não sabemos a data verdadeira. No caso de não conhecermos a data verdadeira, marcamos o dateCircacampo como Ye fornecemos uma data suficientemente próxima, marcada como o "1º", como

1st March, 2013  // We don't know the day of the month
1st January, 2013  // We don't know the month/day of the year
1st January, 2000  // We don't know the month/day/year, we only know the century
user7007
fonte
0

visão global

Existem muitas representações possíveis e, portanto, esquemas de banco de dados, para armazenar datas e horários nebulosos (ou mesmo datas nebulosas):

  1. Data e hora e código indicando sua precisão ou exatidão
  2. Data e hora e intervalo em que existem várias possibilidades para representar um intervalo:
    1. Representa todos os intervalos como uma quantidade inteira (ou outra quantidade numérica) de alguma unidade fixa, por exemplo, dias, minutos, nanossegundos.
    2. Representa um intervalo como uma quantidade inteira (ou outra numérica) e um código indicando suas unidades.
  3. Data e hora de início e término
  4. Corda
  5. Distribuição de probabilidade:
    1. Quantidades decimais ou de ponto flutuante para os parâmetros que especificam uma distribuição específica em uma família específica, por exemplo, média e desvio padrão de uma distribuição normal.
    2. Função de distribuição de probabilidade, por exemplo, como um código (pesquisa) (potencialmente com parâmetros de valores específicos) ou como uma expressão em uma linguagem, formato ou representação suficientemente expressiva.

[1], [2] e [3] são todos (implicitamente) intervalos uniformes, isto é, um conjunto de (igualmente) pontos possíveis no tempo.

[4] é a mais expressiva, ou seja, ao permitir quaisquer frases ou frases possíveis (ou pelo menos arbitrariamente longas) em linguagem escrita. Mas também é o mais difícil de trabalhar. No limite, a IA em nível humano seria necessária para lidar com valores arbitrários. Na prática, o intervalo de valores possíveis precisaria ser severamente restringido, e valores 'estruturados' alternativos provavelmente seriam preferidos para muitas operações, por exemplo, classificação e pesquisa.

[5] é provavelmente o mais geral compacto representação que é (um pouco) prático.

Intervalos uniformes

Intervalos uniformes são a maneira mais simples e compacta de representar um conjunto de (possíveis) valores de data e hora.

Para [1], partes do valor de data e hora são ignoradas, isto é, as partes correspondentes a unidades mais finas que a precisão ou exatidão indicada; caso contrário, isso é equivalente a [2] e o código de precisão / exatidão é equivalente a um intervalo com as mesmas unidades (e uma quantidade implícita de 1).

[2] e [3] são expressivamente equivalentes. [1] é estritamente menos expressivo do que qualquer um, pois existem intervalos efetivos que não podem ser representados por [1], ex. uma data e hora difusa equivalente a um intervalo de 12 horas que abrange um limite de data.

[1] é mais fácil para os usuários inserirem do que qualquer outra representação e geralmente deve exigir (pelo menos um pouco) menos digitação. Se a data e a hora puderem ser inseridas em várias representações de texto, por exemplo, "2013", "2014-3", "2015-5-2", "30/07/2016 11p", "31-07-2016 18:15" , a precisão ou a exatidão também podem ser inferidas automaticamente a partir da entrada.

A exatidão ou precisão de [1] também é mais fácil de converter em um formulário a ser transmitido aos usuários, por exemplo, '2015-5 com precisão de mês' para "maio de 2015", versus "13 de maio de 2015 2p, mais ou menos 13,5 dias" (note que este último não pode ser representado por [1] de qualquer maneira).

Cordas

Na prática, os valores das strings precisarão ser convertidos em outras representações para consulta, classificação ou comparação de vários valores. Portanto, embora qualquer linguagem natural (humana) escrita seja estritamente mais expressiva que [1], [2], [3] ou [5], ainda não temos os meios de lidar com muito além das representações ou formatos padrão de texto. Dado isso, essa é provavelmente a representação menos útil por si só .

Uma vantagem dessa representação é que, na prática, os valores devem ser apresentáveis ​​aos usuários como estão e não exigem que a transformação seja facilmente compreensível.

Distribuições de probabilidade

As distribuições de probabilidade generalizam as representações de intervalo uniformes [1], [2], [3] e (sem dúvida) são equivalentes à representação de seqüência de caracteres (geral) [4].

Uma vantagem das distribuições de probabilidade sobre as strings é que a primeira é inequívoca.

[5-1] seria apropriado para valores que (principalmente) estejam em conformidade com uma distribuição existente, por exemplo, um valor de data e hora gerado por um dispositivo cujas medidas são conhecidas (ou consideradas) como estando em conformidade com uma distribuição específica.

[5-2] é provavelmente a melhor maneira (um pouco) prática de representar de maneira compacta os valores arbitrários de 'fuzzy datetime'. É claro que a computabilidade das distribuições de probabilidade específicas usadas é importante e existem definitivamente problemas interessantes (e talvez impossíveis) a serem resolvidos ao consultar, classificar ou comparar valores diferentes, mas muito disso provavelmente já é conhecido ou resolvido em algum lugar existente. literatura matemática e estatística, então isso definitivamente se destaca como uma representação extremamente geral e inequívoca.

Kenny Evitt
fonte
-1

Eu realmente gosto da solução de James Anderson - Limitar com precisão as datas é o caminho para obter a estrutura de consulta mais flexível. Outra maneira de conseguir o mesmo é usar um centro de início, fim ou mesmo datemais um interval(disponível pelo menos no PostgreSQL , Oracle e SQLAlchemy ).

l0b0
fonte
-2

No seu caso, você precisa apenas de ano, mês e dia. Ano e mês são obrigatórios, o dia é opcional. Eu usaria algo assim:

year smallint not null,
month smallint not null,
day smallint

Além disso, você ainda pode usar índices de maneira muito eficaz. As filas (tiny = minus) ficam um pouco mais "complicadas" (mais longas).

Marinheiro Danubiano
fonte
1
Mas isso significa que, se a imprecisão devorar a parte do mês também, essa abordagem falhará.
Anurag Kalia
1
@AnuragKalia - torne o campo do mês anulável. Não há razão para que isso não possa ser reconfigurado posteriormente.
Jeffo
Aquilo foi apenas um exemplo. A solução deve ser geral o suficiente para acomodar problemas futuros. Se o intervalo especificado for de 15 de março a 22 de março de 2013, essa abordagem não funcionará. A resposta min-max acima é a mais geral de todas.
Anurag Kalia
1
Você encontrou esse requisito no post do OP ou é apenas a sua fantasia?
Sailor Danubian
Tornar o mês anulável permite especificar um dia, mas não um mês. Também não faz sentido. Quando foi 1978-??-31?
MSalters
-2

Simplesmente armazenaria a hora exata das datas normais e tornaria genérica a parte da hora da data nebulosa, como 00:00:00. Eu faria todas as datas confusas no primeiro dia do mês.

Quando você consulta, você

  1. verifique os períodos em que a hora também é igual a 00:00:00 (difusa)
  2. verifique os períodos em que a hora NÃO é igual a 00:00:00 (real)
  3. verifique os períodos, mas ignore a parte da hora (combinada)

Existem soluções melhores do que isso, mas eu pessoalmente odeio metadados (dados sobre meus dados). Ele apenas tem o hábito de ficar fora de controle depois de um tempo.

Capitão Kenpachi
fonte
2
como isso lidaria com data real tendo tempo 00:00:00?
mosquito
Embora seja teoricamente possível adicionar uma data real com esse horário, isso não acontecerá. Vi tabelas com milhões de linhas e nenhuma delas tinha um valor datetime em que o horário era 00:00:00. O pragmatismo supera a convenção.
Capitão Kenpachi