Eu herdei um banco de dados grande (SQLServer) com centenas de colunas que representam quantidades de uma coisa ou de outra. As unidades para esses valores (por exemplo, "galões", "polegadas" etc.) são armazenadas no campo MS_Description de Propriedades estendidas. Gostaria de saber se existe uma maneira melhor de armazenar essas informações. Suponho que seja bom para fins de documentação, mas seria difícil fazer cálculos robustos de conversão de unidades com base nesses dados. Neste ponto, não estou preparado para fazer uma mudança invasiva, mas se tiver a chance de fazê-lo, qual é a melhor prática recomendada a esse respeito? As opções, em cima da minha cabeça, podem incluir:
- Altere o nome da coluna para as unidades incluídas (por exemplo, "TotalVolumeInGallons". Isso tornaria as informações um pouco mais prontamente disponíveis, mas ainda me parecem fracas.)
- Adicione uma coluna "Unidades" separada para corresponder a todas as colunas "Quantidade" (essa coluna pode ser nvarchar OU pode ser uma chave estrangeira para uma tabela de unidades separada, o que pode facilitar o cálculo de conversões de unidades. muitas colunas podem dobrar bastante o tamanho do meu banco de dados - com dados terrivelmente redundantes.)
- Crie um novo campo em Propriedades estendidas dedicado especificamente para unidades. (Infelizmente, acho que isso não pode ser uma chave estrangeira para uma tabela de unidades.)
- Existe outra ideia que estou ignorando?
ATUALIZAÇÃO: Depois de ler a resposta de @Todd Everett, uma possível solução me ocorreu, então vou em frente e respondo minha própria pergunta. (Ver abaixo)
Respostas:
Como você menciona centenas de colunas, consideraria um design de EAV . Enquanto Joe Celko adverte contra isso , acho que pode ser aplicável no seu caso de uso. Parece que todos os seus "valores" são números, para evitar os problemas de elenco que Joe descreve e a necessidade de transformar cada "valor" em uma string. Funcionará ainda melhor se todos os valores forem números inteiros, mas também poderá funcionar se alguns forem decimais. Dadas as unidades de medida, você poderia dar um passo adiante e implementar um modelo de estilo "modelo de dados universal", baseado neste artigo de David Hay e também descrito em seu livro Padrões de modelo de dados: convenções de pensamento. Este modelo tem a vantagem adicional de configurar quais "valores" se aplicam a quais "itens", se você precisar. Uma etapa adicional mostrada no livro na página 162 é uma tabela de conversão de unidades de medida que você pode usar para converter entre as diferentes unidades de medida. Aqui está um exemplo:
Isto significa que para converter de Kg para Lb o primeiro passo é multiplicar Kg por 2,2. Também há uma constante se uma conversão também deve incluir um valor constante e a capacidade de criar várias etapas. Portanto, ao converter, digamos, Celsius para Fahrenheit, você multiplica Celsius por 1,8 e depois adiciona 32. A chave seria UOM, UOM e Etapa de cálculo.
Esse é o meu valor de 2 centavos. Espero que essas referências lhe permitam refletir bem, caso você tenha a chance de reiniciar o design atual.
fonte
Todo o trabalho.
Observe que, no segundo caso, você não pode adicionar maçãs e laranjas e, portanto, os dados são excepcionalmente fáceis de serem sujeitos a erros de interpretação.
Observe também que as conversões não podem ser muito seguras e são suscetíveis a erros de arredondamento, estouros excessivos etc.
Além disso, existem problemas físicos, como a gravidade e a temperatura específicas. Converter 20 galões de água em libras exigiria que você conhecesse a densidade da água. Mas a densidade da água muda com a temperatura; portanto, você pode precisar conhecer a densidade contemporânea da medição ou a temperatura da mesma forma e usar um fator de correção de volume.
No caso das propriedades Estendidas, isso é bom apenas para documentação - um bom nome de coluna é melhor para documentação. O problema com a coluna implicada como estando em uma unidade fixa pelo nome é que você acaba se esquecendo quando altera as unidades de medida - o novo cliente quer óleo em barris e não em galões - e isso seria bom, pois os dados estão em seu próprio banco de dados, mas o nome da coluna agora é enganoso.
Outra opção é armazenar versões canônicas em unidades fixas (ou seja, sempre quilogramas e metros), além das diversas medidas originais. As operações agregadas nas unidades fixas devem ser boas (exceto que você não adicionaria temperaturas, por exemplo), mas você não perde a medida original.
fonte
Uma solução simples que funcionou bem para mim no passado é armazenar todos os seus dados nas unidades 'base'. Por exemplo, sua unidade base para comprimentos pode ser milímetros e sua unidade base para pesos pode ser quilogramas. Esta solução pode resultar na necessidade de converter alguns dos seus dados existentes na unidade base, se ainda não estiverem.
Depois de ter todos os dados nas unidades base padrão, não há necessidade de armazenar a unidade no próprio banco de dados, já que agora é uma suposição geral do sistema. As unidades exibidas necessárias para cada tipo de unidade (por exemplo, se deve exibir mm, polegadas, cm, m para comprimento) tornam-se um problema de domínio de aplicativo / cliente, que pode ser salvo no armazenamento local.
As tabelas de conversão de unidades para conversão entre as várias unidades suportadas podem ser codificadas no aplicativo, pois as novas unidades de medida mudam muito raramente.
NB, uma solução relacionada a outro problema é que, ao armazenar carimbos de data e hora em um banco de dados, os armazene sempre na unidade 'base' - UTC .
Outro Q&A relacionado sobre o tópico ...
/programming/12977021/best-practice-for-storing-weights-in-a-sql-database
Isso contém algumas informações boas sobre por que usar um tipo de coluna de ponto flutuante é o melhor caminho a seguir ao armazenar medições do mundo real.
fonte
Como qualquer unidade pode ser convertida em outra unidade do mesmo tipo Com a fórmula:
Eu criaria uma tabela que contém os tipos de unidade mais esses 4 valores.
Depois de adicionar todas as medidas que você provavelmente converterá de e para os dois lados da lista, execute uma Consulta na qual você insere a operação inversa simplesmente negando as compensações e trocando o multiplicando e o denominador e a Unidade To e From Unit.
Para adicionar conversão entre todos os tipos, uma junção cruzada Com alguns filtros, é possível inserir as conversões restantes.
fonte
Depois de ler a resposta de @Todd Everett, uma solução me ocorreu, então vou adiante e responder minha própria pergunta. O que eu acho que eu vou fazer é criar um separada
ColumnUnits
mesa, com quatro colunas:Schema
,Table
,Column
,UnitsID
(onde UnitsID é FK a um separadaUnitsOfMeasure
mesa), mapeando assim, qualquer coluna para sua Unidade de medida associada. Obviamente, a maior desvantagem dessa idéia é que os desenvolvedores precisariam se lembrar de editar essa tabela sempre que renomearem uma coluna ou tabela [ talvez use um gatilho DDL ? ], caso contrário, o sistema irá quebrar. Mas, supondo que tais renomeações sejam raras, e a dev-shop pequena (apenas uma pessoa, no meu caso), essa arquitetura deve ser viável. A vantagem é que nenhuma alteração invasiva precisa ser feita no banco de dados atual, e eu só tenho que armazenar o valor uma vez para cada coluna, em vez de uma vez por linha, como exigiria minha segunda opção na postagem original.fonte