Odpowiedni typ danych do przechowywania wartości procentowych?

Odpowiedzi:

132

Zakładając dwa miejsca po przecinku na procentach, typ danych, których używasz, zależy od tego, jak planujesz je przechowywać. Jeśli zamierzasz przechowywać ich ułamkowy odpowiednik (np. 100,00% przechowywane jako 1,0000), przechowywałbym dane w decimal(5,4)typie danych z CHECKograniczeniem, które zapewnia, że ​​wartości nigdy nie przekraczają 1,0000 (zakładając, że jest to limit) i nigdy nie spadają poniżej 0 (zakładając, że jest to podłoga). Jeśli zamierzasz przechowywać ich wartość nominalną (np. 100,00% jest przechowywane jako 100,00), to powinieneś używać decimal(5,2)z odpowiednim CHECKograniczeniem. W połączeniu z dobrą nazwą kolumny wyjaśnia innym programistom, jakie są dane i jak są one przechowywane w kolumnie.

Tomasz
źródło
12
Czy nie powinno być decimal(5,2)tam, gdzie 2 oznacza liczbę cyfr po separatorze dziesiętnym?
Boris Callens
2
@BorisCallens - Nie mogę uwierzyć, że tęskniłem za tym przez te wszystkie lata. Tak, to pomyłka. decimal(5,2)jest tym, co powinno zostać uchwycone za pomocą ograniczenia sprawdzającego.
Thomas
4
Zakładam, że pierwotnie miał decimal(5,4)i został zmieniony decimal(5,2)po powyższym komentarzu ... Myślę, że decimal(5,4)byłaby lepsza definicja - tj. Chcesz zapisać od 0 do 1 z 2 miejscami po przecinku, a nie od 0 do 100. Powód, dla którego wartość procentowa jest poza 100; więc 100% to 100/100, czyli 1. Zrobienie tego w ten sposób ma większy sens w większości przypadków (np. 100% * 100% = 100%nie 10000%; 1 * 1 = 1).
JohnLBevan
4
@JohnLBevan - wydaje na to, jak są przechowywane. Jeśli wartości mają być przechowywane tak, jak są wyświetlane (np. 100.00), Potrzebujesz decimal(5,2). Jeśli wartości mają być przechowywane jako ułamki (np. 1.0000), Potrzebujesz decimal(5,4). Zaktualizuje post.
Thomas
Czy ktoś może wyjaśnić, dlaczego potrzebujesz 4 miejsc po przecinku? Nie możesz użyć 2? Na przykład 0,91 === 91% lub 1,00 === 100%. Wdrażam to teraz i zastanawiałem się nad zyskiem z 4 miejscami. Coś w rodzaju Pct decimal (10, 2) CHECK (Pct> =. 01 AND Pct <= 1). Z góry dziękuję.
MH
31
  • Trzymaj jako decimal.
  • Dodaj ograniczenia sprawdzające, jeśli chcesz ograniczyć zakres (np. Od 0 do 100%; w niektórych przypadkach mogą istnieć ważne powody, aby przekroczyć 100% lub potencjalnie nawet do wartości ujemnych).
  • Traktuj wartość 1 jako 100%, 0,5 jako 50% itd. Dzięki temu wszelkie operacje matematyczne będą działać zgodnie z oczekiwaniami (tj. W przeciwieństwie do używania wartości 100 jako 100%).
  • Zmień dokładność i skalę zgodnie z wymaganiami (są to dwie wartości w nawiasach columnName decimal(precision, scale). Precyzja mówi o całkowitej liczbie cyfr, które można przechowywać w liczbie, skala mówi, ile z nich jest po przecinku, więc decimal(3,2)jest to liczba, którą można przedstawić jak #.##; decimal(5,3)byłoby ##.###.
  • decimali numericzasadniczo są tym samym. Jednak decimaljest zgodny z ANSI, więc zawsze używaj go, chyba że określono inaczej (np. Standardy kodowania firmy).

Przykładowe scenariusze

  • Dla twojego przypadku (0,00% do 100,00%), jaki chcesz decimal(5,4).
  • W najczęstszym przypadku (od 0% do 100%), jaki chcesz decimal(3,2).
  • W obu powyższych przypadkach ograniczenia sprawdzające byłyby takie same

Przykład:

if object_id('Demo') is null
create table Demo
    (
        Id bigint not null identity(1,1) constraint pk_Demo primary key
        , Name nvarchar(256) not null constraint uk_Demo unique 
        , SomePercentValue decimal(3,2) constraint chk_Demo_SomePercentValue check (SomePercentValue between 0 and 1)
        , SomePrecisionPercentValue decimal(5,2) constraint chk_Demo_SomePrecisionPercentValue check (SomePrecisionPercentValue between 0 and 1)
    )

Dalsze czytanie:

JohnLBevan
źródło
4

Zgadzam się z Thomasem i wybrałbym rozwiązanie DECIMAL (5,4) przynajmniej dla aplikacji WPF.

Zajrzyj do ciągu formatu liczbowego MSDN, aby dowiedzieć się, dlaczego: http://msdn.microsoft.com/en-us/library/dwhawy9k#PFormatString

Specyfikator formatu procentu („P”) mnoży liczbę przez 100 i konwertuje ją na ciąg reprezentujący wartość procentową.

Wtedy możesz użyć tego w swoim kodzie XAML:

DataFormatString="{}{0:P}"
pjehan
źródło
2

Jeśli poziom precyzji to 2 miejsca po przecinku, to „smallint” poradzi sobie z tym na najmniejszej przestrzeni (2 bajty). Przechowujesz procent pomnożony przez 100.

EDYCJA: prawdopodobnie lepiej pasuje typ dziesiętny . Wtedy nie musisz ręcznie skalować. Zajmuje 5 bajtów na wartość.

mdma
źródło
Microsoft złamał tak wiele swoich linków .....
pcnate
0

Użyj numeric (n, n), gdzie n ma wystarczającą rozdzielczość, aby zaokrąglić do 1,00. Na przykład:

declare @discount numeric(9,9)
    , @quantity int
select @discount = 0.999999999
    , @quantity = 10000

select convert(money, @discount * @quantity)
user2202942
źródło
3
To pytanie ma dość wysoko ocenioną akceptowaną odpowiedź sprzed ponad trzech lat. Jeśli szukasz odpowiedzi na stare pytania, zajrzyj tutaj: stackoverflow.com/unansrated
valverij