ARRAY — yaratish, operatorlar, ANY, ALL, unnest
Muammodan boshlaylik
Foydalanuvchilar tizimida har bir foydalanuvchining bir nechta teli raqami bo'lishi mumkin. Yoki mahsulotning bir nechta tegi bor.
Oddiy yechim — alohida jadval: telefon_raqamlar(foydalanuvchi_id, raqam). To'g'ri yechim — lekin har bir qo'shimcha so'rov uchun JOIN kerak.
Ba'zan ma'lumot shunchaki sodda ro'yxat — murakkab munosabat emas. Masalan, teglar, rasmlar ro'yxati, ruxsat kodlari. Bunday holat uchun PostgreSQL da ARRAY turi bor.
ARRAY nima?
ARRAY — bir xil turdagi qiymatlar to'plami, bitta ustunda saqlanadi. Har bir element indeks orqali olinadi.
Hayotiy o'xshatma: xarid qilish ro'yxati. Daftarning bitta satrida bir nechta mahsulot yozilgan: "non, sut, tuxum". Bu satr — array. Alohida jadvalga chiqarish kerak emas — shunchaki bitta joyda ro'yxat.
Alohida jadval: ARRAY:
──────────────────── ────────────────────────────
user_id │ telefon user_id │ telefonlar
────────┼───────── ────────┼─────────────────────
1 │ 901234567 1 │ {901234567, 712345678}
1 │ 712345678
JOIN kerak emas ✅
JOIN kerak, 2 qator 1 qator ✅
ARRAY ustun yaratish
Har qanday turga [] qo'shilsa — array:
CREATE TABLE foydalanuvchilar (
id SERIAL PRIMARY KEY,
ism TEXT,
telefonlar TEXT[], -- ← TEXT array
teglar TEXT[], -- ← TEXT array
baholar INTEGER[] -- ← INTEGER array
);
Ma'lumot qo'shish
INSERT INTO foydalanuvchilar (ism, telefonlar, teglar, baholar) VALUES
('Ali', ARRAY['901234567', '712345678'], ARRAY['vip', 'aktiv'], ARRAY[85, 90, 78]),
('Vali', ARRAY['935678901'], ARRAY['yangi'], ARRAY[70]),
('Soli', ARRAY['998765432', '901112233'], ARRAY['vip', 'premium'], ARRAY[95, 88, 92]),
('Jamol', NULL, ARRAY['aktiv'], ARRAY[60, 75]);
Yoki {} sintaksisi bilan:
INSERT INTO foydalanuvchilar (ism, telefonlar) VALUES
('Kamol', '{"998001122", "712334455"}');
Elementlarni o'qish
PostgreSQL array indeksi 1 dan boshlanadi — boshqa ko'pgina tillardan farqli:
SELECT
ism,
telefonlar, -- barcha elementlar
telefonlar[1], -- birinchi element
telefonlar[2] -- ikkinchi element
FROM foydalanuvchilar;
ism │ telefonlar │ telefonlar[1] │ telefonlar[2]
--------+------------------------+---------------+---------------
Ali │ {901234567,712345678} │ 901234567 │ 712345678
Vali │ {935678901} │ 935678901 │ NULL
Soli │ {998765432,901112233} │ 998765432 │ 901112233
Jamol │ NULL │ NULL │ NULL
Kesim (slice) — bir nechta element
SELECT baholar[1:2] FROM foydalanuvchilar WHERE ism = 'Soli';
-- {95, 88} ← 1-dan 2-gacha
Array uzunligi va elementlar soni
SELECT
ism,
array_length(telefonlar, 1) AS telefon_soni,
-- 1 → birinchi o'lcham (ko'p o'lchovli array uchun 2, 3...)
cardinality(teglar) AS teg_soni
-- cardinality — NULL ni ham hisobga olgan array_length
FROM foydalanuvchilar;
ism │ telefon_soni │ teg_soni
--------+--------------+----------
Ali │ 2 │ 2
Vali │ 1 │ 1
Soli │ 2 │ 2
Jamol │ NULL │ 1
Filtrlash operatorlari
ANY — elementlardan biri teng
"Teglar ichida 'vip' bor foydalanuvchilar":
SELECT ism FROM foydalanuvchilar
WHERE 'vip' = ANY(teglar);
ism
------
Ali
Soli
ANY(massiv) — massivning birorta elementi shartga mos kelsa rost. = ANY — IN ga o'xshash, lekin array ustun uchun.
ALL — barcha elementlar teng
"Barcha baholari 80 dan yuqori":
SELECT ism FROM foydalanuvchilar
WHERE 80 < ALL(baholar);
ism
------
Ali
Soli
ALL(massiv) — massivning barcha elementlari shartga mos kelsa rost.
@> — ichida bor
Array ichida berilgan array to'liq bormi:
-- 'vip' va 'aktiv' ikkalasi ham bor foydalanuvchilar
SELECT ism FROM foydalanuvchilar
WHERE teglar @> ARRAY['vip', 'aktiv'];
ism
-----
Ali
Soli da 'vip' bor lekin 'aktiv' yo'q — tushib qoldi.
&& — kesishma bormi
Ikki arraydan birorta umumiy element bormi:
-- 'premium' yoki 'vip' tegi bor foydalanuvchilar
SELECT ism FROM foydalanuvchilar
WHERE teglar && ARRAY['premium', 'vip'];
ism
------
Ali
Soli
Array o'zgartirish
Element qo'shish — ||
-- Oxiriga qo'shish
UPDATE foydalanuvchilar
SET teglar = teglar || ARRAY['tasdiqlangan']
WHERE ism = 'Vali';
-- Boshiga qo'shish
UPDATE foydalanuvchilar
SET teglar = ARRAY['super'] || teglar
WHERE ism = 'Ali';
Element o'chirish — array_remove
UPDATE foydalanuvchilar
SET teglar = array_remove(teglar, 'yangi')
WHERE ism = 'Vali';
-- 'yangi' tegi o'chirildi
Almashtirish — array_replace
UPDATE foydalanuvchilar
SET teglar = array_replace(teglar, 'aktiv', 'faol')
WHERE ism = 'Ali';
-- 'aktiv' → 'faol' ga almashdi
unnest — arrayni qatorlarga yoyish
Array elementlarini alohida qatorlar sifatida ko'rsatish:
SELECT ism, unnest(teglar) AS teg
FROM foydalanuvchilar;
ism │ teg
--------+-----------
Ali │ vip
Ali │ aktiv
Vali │ yangi
Soli │ vip
Soli │ premium
Jamol │ aktiv
Har bir element alohida qator bo'ldi. Bu — LATERAL bilan birga ayniqsa kuchli.
unnest bilan raqamlash
SELECT
ism,
ordinality AS tartib,
teg
FROM foydalanuvchilar,
unnest(teglar) WITH ORDINALITY AS t(teg, ordinality);
ism │ tartib │ teg
--------+--------+-----------
Ali │ 1 │ vip
Ali │ 2 │ aktiv
Vali │ 1 │ yangi
Soli │ 1 │ vip
Soli │ 2 │ premium
WITH ORDINALITY — har elementga tartib raqami beradi.
array_agg — qatorlarni arrayga yig'ish
unnest ning aksi — alohida qatorlardan array yaratish:
-- Har shahar uchun foydalanuvchilar ro'yxati
SELECT
shahar,
array_agg(ism ORDER BY ism) AS foydalanuvchilar
FROM foydalanuvchilar
GROUP BY shahar;
shahar │ foydalanuvchilar
------------+------------------------
Toshkent │ {Ali, Jamol, Soli}
Samarqand │ {Vali}
Tez-tez uchraydigan xatolar
Indeks 0 dan boshlanadi deb o'ylash:
-- ❌ — PostgreSQL da array indeksi 1 dan boshlanadi
SELECT telefonlar[0] FROM foydalanuvchilar;
-- NULL qaytadi — xato emas, lekin noto'g'ri
-- ✅
SELECT telefonlar[1] FROM foydalanuvchilar;
Boshqa tillarda (Python, JS) 0 dan boshlanadi — PostgreSQL da 1 dan. Bu ko'p adashtiradi.
NULL array va bo'sh array farqini bilmaslik:
-- NULL array — umuman qiymat yo'q
-- Bo'sh array — qiymat bor, lekin elementlar yo'q
SELECT array_length(NULL::TEXT[], 1); -- NULL
SELECT array_length(ARRAY[]::TEXT[], 1); -- NULL (PostgreSQL da bo'sh array uzunligi NULL)
SELECT cardinality(ARRAY[]::TEXT[]); -- 0
cardinality bo'sh array uchun 0 qaytaradi — array_length esa NULL. Nol elementni tekshirishda cardinality ishlatgan ma'qul.
Xulosa
ARRAY — bitta ustunda bir xil turdagi qiymatlar ro'yxati. Kichik, sodda ro'yxatlar uchun alohida jadval va JOIN kerak emas.
telefonlar[1] → birinchi element (1 dan boshlanadi!)
ANY(massiv) → elementlardan biri shartga mos
ALL(massiv) → barcha elementlar shartga mos
@> → array ichida boshqa array bor
&& → umumiy element bor
unnest → arrayni qatorlarga yoy
array_agg → qatorlarni arrayga yig'
Qachon ARRAY, qachon alohida jadval:
ARRAY: Alohida jadval:
────────────── ──────────────────
Sodda ro'yxat Murakkab munosabat
Tartib muhim Qo'shimcha ustunlar kerak
Ko'p JOIN noqulay Katta hajmdagi ma'lumot
Teglar, ruxsatlar Pul operatsiyalari, buyurtmalar
Keyingi dars
25-dars: Full-text Search — tsvector, tsquery, to_tsvector, plainto_tsquery