43 / 100

DECIMAL

O'nlik kasr sonlar: NUMERIC

Kirish: Ushbu qo'llanmada siz PostgreSQL DECIMAL ma'lumot turi yordamida ma'lumotlar bazasida o'ta aniq sonli ma'lumotlarni saqlashni o'rganasiz.

PostgreSQL DECIMAL ma'lumot turiga kirish

PostgreSQL DECIMAL turi o'zining mutlaq aniqligi tufayli moliyaviy hisob-kitoblar, pul miqdorlari va xatolikka yo'l qo'yib bo'lmaydigan ilmiy hisoblar uchun eng to'g'ri tanlovdir.

DECIMAL turidagi ustunni yaratish sintaksisi:

query.sql
CREATE TABLE table_name (
  column_name DECIMAL(p, s),
  ...
);

DEC va NUMERIC kalit so'zlari DECIMAL ning to'liq sinonimi bo'lib, ularni bir-birining o'rnida erkin ishlatishingiz mumkin:

query.sql
CREATE TABLE table_name (
  column_name DEC(p, s),
  ...
);

Ushbu sintaksisda:

  • p (precision — aniqlik): butun va kasr qismlarni o'z ichiga olgan umumiy raqamlar soni. p qiymati 1 dan 1000 gacha bo'lishi mumkin.
  • s (scale — miqyos): o'nlik nuqtadan keyin (o'ng tomonda) keluvchi raqamlar soni.

Masalan, DEC(11, 2) ustuni jami 11 ta raqamdan iborat sonni saqlaydi, shulardan 2 tasi o'nlik nuqtadan keyingi tiyinlar (sentlar) qismidir.

Agar miqyos (s) ko'rsatmasangiz, u sukut bo'yicha 0 deb hisoblanadi (DEC(p, 0)).

Agar aniqlik va miqyos ikkalasini ham ko'rsatmasangiz (DEC yoki NUMERIC), PostgreSQL o'nlik nuqtagacha 131,072 tagacha va nuqtadan keyin 16,383 tagacha raqamlarni saqlash imkonini beradi.

PostgreSQL DECIMAL turiga misol

Birinchidan, ombordagi tovarlar qoldig'ini saqlash uchun inventories jadvalini yaratamiz:

query.sql
CREATE TABLE inventories (
  id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  product_name VARCHAR(255) NOT NULL,
  quantity INT NOT NULL CHECK (quantity >= 0),
  price DEC(11, 2) NOT NULL CHECK (price > 0),
  brand VARCHAR(255) NOT NULL
);

Ikkinchidan, jadvalga ma'lumotlar kiritamiz:

query.sql
INSERT INTO
  inventories (product_name, quantity, price, brand)
VALUES
  ('iPhone 16 Pro', 50, 999.99, 'Apple'),
  ('iPhone 16 Pro Max', 40, 1099.99, 'Apple'),
  ('iPhone 16 Plus', 55, 899.99, 'Apple'),
  ('Galaxy S24 Ultra', 45, 1199.99, 'Samsung'),
  ('Galaxy S24 Plus', 50, 999.99, 'Samsung'),
  ('Galaxy Z Fold 6', 30, 1799.99, 'Samsung'),
  ('Galaxy Z Flip 6', 35, 999.99, 'Samsung'),
  ('Pixel 9', 50, 799.99, 'Google'),
  ('Pixel 9 Pro', 40, 999.99, 'Google'),
  ('Pixel 9 Pro Fold', 25, 1799.99, 'Google')
RETURNING *;

Natija:

matn
id |   product_name    | quantity |  price  |  brand
----+-------------------+----------+---------+---------
  1 | iPhone 16 Pro     |       50 |  999.99 | Apple
  2 | iPhone 16 Pro Max |       40 | 1099.99 | Apple
  3 | iPhone 16 Plus    |       55 |  899.99 | Apple
  4 | Galaxy S24 Ultra  |       45 | 1199.99 | Samsung
  5 | Galaxy S24 Plus   |       50 |  999.99 | Samsung
  6 | Galaxy Z Fold 6   |       30 | 1799.99 | Samsung
  7 | Galaxy Z Flip 6   |       35 |  999.99 | Samsung
  8 | Pixel 9           |       50 |  799.99 | Google
  9 | Pixel 9 Pro       |       40 |  999.99 | Google
 10 | Pixel 9 Pro Fold  |       25 | 1799.99 | Google

Uchinchidan, har bir brend bo'yicha tovarlarning umumiy qiymatini hisoblaymiz:

query.sql
SELECT
  brand,
  SUM(quantity * price)
FROM
  inventories
GROUP BY
  brand;

Natija:

matn
 brand  |    sum
---------+-----------
 Google  | 124998.85
 Apple   | 143498.55
 Samsung | 192998.40

Manfiy miqyos (Negative scale)

PostgreSQL 15 versiyasidan boshlab o'nlik kasr ustunlarini manfiy miqyos (negative scale) bilan e'lon qilish mumkin:

query.sql
DEC(p, -s)

Bunda PostgreSQL sonni o'nlik nuqtadan chap tomonga qarab yaxlitlaydi.

Masalan:

query.sql
CREATE TABLE items (
  item_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  value DEC(5, -2) NOT NULL
);

INSERT INTO
  items (value)
VALUES
  (12345),
  (67890) 
RETURNING *;

Natija:

matn
item_id | value
---------+-------
       1 | 12300
       2 | 67900

Miqyos -2 bo'lgani uchun, PostgreSQL qiymatlarni eng yaqin yuzliklargacha yaxlitlaydi.

Yaxlitlash (ROUND)

O'rtacha qiymatni hisoblab, uni ma'lum xonagacha yaxlitlash uchun ROUND() funksiyasidan foydalanishingiz mumkin:

query.sql
SELECT
  brand,
  AVG(quantity * price),
  ROUND(AVG(quantity * price), 2)
FROM
  inventories
GROUP BY
  brand;

Natija:

matn
 brand  |        avg         |  round
---------+--------------------+----------
 Google  | 41666.283333333333 | 41666.28
 Apple   | 47832.850000000000 | 47832.85
 Samsung | 48249.600000000000 | 48249.60

Maxsus qiymatlar

Oddiy sonlardan tashqari, DECIMAL turi IEEE 754 standartiga mos keluvchi maxsus qiymatlarni ham qo'llab-quvvatlaydi:

  • Infinity — cheksiz katta son;
  • -Infinity — cheksiz kichik son;
  • NaN (not-a-number) — noto'g'ri hisob-kitob natijasida kelib chiquvchi sonsiz qiymat.

SQL so'rovlarida ushbu maxsus qiymatlardan foydalanayotganda ularni bittalik tirnoq ichiga olishingiz kerak: 'Infinity', '-Infinity', 'NaN'.

Xulosa

  • Yuqori aniqlik talab qilinadigan sonlar va moliyaviy hisob-kitoblar uchun DECIMAL yoki NUMERIC turidan foydalaning.
  • DECIMAL(p, s) sintaksisida p umumiy raqamlar soni, s esa o'nlik nuqtadan keyingi xonalar sonidir.