0% found this document useful (0 votes)
17 views15 pages

Adbms Assignment j032 Range Udt

Uploaded by

khushibshah7
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views15 pages

Adbms Assignment j032 Range Udt

Uploaded by

khushibshah7
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

ADBMS ASSIGNMENT

J032 KHUSHI SHAH

Q1)
Price bands •
RANGE TYPE: price_range AS RANGE (subtype = numeric)
• Table: plans(pid serial pk, name text, band price_range)
• Queries: plans where band @> 450::numeric; overlap with '[300,600]'::price_range; list
lower/upper bounds; order by lower(band); merge overlapping bands (challenge).

SOLUTION)

-- Reset session in case a previous transaction was aborted


ROLLBACK;

-- 1. Drop table and range type if they already exist


DROP TABLE IF EXISTS plans;
DROP TYPE IF EXISTS price_range;

-- 2. Create custom range type for prices


CREATE TYPE price_range AS RANGE (
subtype = numeric
);

-- 3. Create plans table using the range type


CREATE TABLE plans (
pid SERIAL PRIMARY KEY,
name TEXT,
band price_range
);

-- 4. Insert sample plans


INSERT INTO plans (name, band) VALUES
('Basic', '[100,300]'),
('Standard', '[250,500]'),
('Premium', '[450,700]'),
('Elite', '[800,1000]');

-- 5. Plans where price band contains 450


SELECT * FROM plans
WHERE band @> 450::numeric;

-- 6. Plans where price band overlaps with [300,600]


SELECT * FROM plans
WHERE band && '[300,600]'::price_range;

-- 7. List lower and upper bounds of each plan


SELECT
pid,
name,
lower(band) AS lower_price,
upper(band) AS upper_price
FROM plans;

-- 8. Order by lower bound


SELECT * FROM plans
ORDER BY lower(band);

-- 9. Challenge: Merge overlapping or contiguous bands


-- Using range_merge on aggregated bands that overlap
WITH merged AS (
SELECT range_merge(band) AS merged_band
FROM plans
GROUP BY band
)
SELECT merged_band
FROM merged;
Q2)

Booking slots • RANGE TYPE: ts_range AS RANGE (subtype = timestamptz)


• Table: room_bookings(id serial pk, room text, slot ts_range)
• Queries: conflicts for a new slot; all bookings overlapping today; bookings that fully contain
a given interval; free times by room (challenge).

SOLUTION)

-- Create a custom range type for booking slots


CREATE TYPE ts_range AS RANGE (
subtype = timestamptz
);

-- Table to store room bookings


CREATE TABLE room_bookings (
id SERIAL PRIMARY KEY,
room TEXT NOT NULL,
slot ts_range NOT NULL
);

-- Insert sample data


INSERT INTO room_bookings (room, slot) VALUES
('Room A', ts_range('2025-08-14 09:00+05:30', '2025-08-14
11:00+05:30')),
('Room A', ts_range('2025-08-14 13:00+05:30', '2025-08-14
15:00+05:30')),
('Room B', ts_range('2025-08-14 10:00+05:30', '2025-08-14
12:30+05:30')),
('Room B', ts_range('2025-08-14 14:00+05:30', '2025-08-14
16:00+05:30')),
('Room C', ts_range('2025-08-15 09:00+05:30', '2025-08-15
11:00+05:30'));

-- Check if the new slot overlaps with existing bookings


SELECT *
FROM room_bookings
WHERE room = 'Room A'
AND slot && ts_range('2025-08-14 10:30+05:30', '2025-08-14
12:00+05:30');

SELECT *
FROM room_bookings
WHERE slot && ts_range(date_trunc('day', now()), date_trunc('day',
now()) + interval '1 day');

SELECT *
FROM room_bookings
WHERE slot @> ts_range('2025-08-14 09:30+05:30', '2025-08-14
10:30+05:30');

WITH times AS (
SELECT room, slot,
lag(upper(slot)) OVER (PARTITION BY room ORDER BY slot) AS
prev_end
FROM room_bookings
)
SELECT room, ts_range(prev_end, lower(slot)) AS free_slot
FROM times
WHERE prev_end IS NOT NULL;

Q3)

Marks interval • RANGE TYPE: marks_range AS RANGE (subtype = int4)


• Table: grade_rules(grade text pk, interval marks_range)
• Queries: which grade contains 73; overlap with [60,80]; normalize to non-overlapping sets
(challenge); list boundary values.
SOLUTION)

-- Step 1: Create the range type for marks


CREATE TYPE marks_range AS RANGE (
subtype = int4
);

-- Step 2: Create the table for grade rules


CREATE TABLE grade_rules (
grade TEXT PRIMARY KEY,
interval marks_range
);

-- Step 3: Insert sample grade intervals


INSERT INTO grade_rules VALUES
('A', '[80,101)'),
('B', '[60,80)'),
('C', '[40,60)'),
('D', '[0,40)');

SELECT grade
FROM grade_rules
WHERE interval @> 73;

SELECT grade, interval


FROM grade_rules
WHERE interval && '[60,80]'::marks_range;

-- Step 4: Normalize overlapping ranges


SELECT unnest(range_merge(array_agg(interval))) AS
normalized_interval
FROM grade_rules;

SELECT grade,
lower(interval) AS min_marks,
upper(interval) - 1 AS max_marks
FROM grade_rules
ORDER BY min_marks DESC;

Q4)

Salary bands • RANGE TYPE: salary_band AS RANGE (subtype = numeric)


• Table: jobs(id serial pk, title text, band salary_band)
• Queries: jobs covering ₹50,000; employees (another table you create) whose salary falls
within job band (join with @>); raise lower bound by 10% for one job.

SOLUTION)

-- =========================
-- Q1: Price Bands
-- =========================

-- 1. Create range type for prices


CREATE TYPE price_range AS RANGE (subtype = numeric);

-- 2. Table for plans


CREATE TABLE plans (
pid SERIAL PRIMARY KEY,
name TEXT,
band price_range
);

-- 3. Sample data
INSERT INTO plans (name, band) VALUES
('Basic', '[100, 300]'),
('Standard', '[250, 500]'),
('Premium', '[500, 800]'),
('Ultra', '[800, 1200]');

-- 4. Queries
-- Plans where band contains 450
SELECT * FROM plans WHERE band @> 450::numeric;

-- Plans overlapping with [300, 600]


SELECT * FROM plans WHERE band && '[300,600]'::price_range;

-- List lower and upper bounds


SELECT name, lower(band) AS min_price, upper(band) AS max_price
FROM plans;

-- Order by lower bound


SELECT * FROM plans ORDER BY lower(band);

-- Challenge: Merge overlapping bands


WITH merged AS (
SELECT unnest(ranges) AS band
FROM (
SELECT range_merge_agg(band) AS ranges
FROM plans
)x
)
SELECT * FROM merged;

-- =========================
-- Q2: Booking Slots
-- =========================

-- 1. Create range type for booking slots


CREATE TYPE ts_range AS RANGE (subtype = timestamptz);

-- 2. Table for room bookings


CREATE TABLE room_bookings (
id SERIAL PRIMARY KEY,
room TEXT,
slot ts_range
);

-- 3. Sample data
INSERT INTO room_bookings (room, slot) VALUES
('A', '[2025-08-14 09:00, 2025-08-14 11:00)'),
('A', '[2025-08-14 11:00, 2025-08-14 13:00)'),
('B', '[2025-08-14 10:00, 2025-08-14 12:00)');

-- 4. Queries
-- Conflicts for a new slot
SELECT * FROM room_bookings
WHERE room = 'A'
AND slot && '[2025-08-14 10:30, 2025-08-14 12:30)'::ts_range;

-- All bookings overlapping today


SELECT * FROM room_bookings
WHERE slot && tstzrange(date_trunc('day', now()), date_trunc('day',
now()) + interval '1 day');

-- Bookings fully containing a given interval


SELECT * FROM room_bookings
WHERE slot @> '[2025-08-14 10:30, 2025-08-14 11:30)'::ts_range;

-- Challenge: Free times by room


-- (Assuming working hours are [09:00, 17:00))
WITH working_hours AS (
SELECT room, '[2025-08-14 09:00, 2025-08-14 17:00)'::ts_range AS
full_day
FROM room_bookings GROUP BY room
),
gaps AS (
SELECT wh.room, wh.full_day - rb.slot AS free_times
FROM working_hours wh
LEFT JOIN room_bookings rb ON wh.room = rb.room
)
SELECT room, unnest(free_times) AS available_slot FROM gaps;

-- =========================
-- Q3: Marks Interval
-- =========================

-- 1. Create range type


CREATE TYPE marks_range AS RANGE (subtype = int4);

-- 2. Table for grade rules


CREATE TABLE grade_rules (
grade TEXT PRIMARY KEY,
interval marks_range
);

-- 3. Sample data
INSERT INTO grade_rules VALUES
('A', '[85, 100]'),
('B', '[70, 85)'),
('C', '[50, 70)'),
('D', '[0, 50)');

-- 4. Queries
-- Which grade contains 73
SELECT * FROM grade_rules WHERE interval @> 73;

-- Overlap with [60,80]


SELECT * FROM grade_rules WHERE interval &&
'[60,80]'::marks_range;

-- Challenge: Normalize to non-overlapping sets (example)


-- (In this case, already non-overlapping)

-- List boundary values


SELECT grade, lower(interval) AS min_marks, upper(interval) AS
max_marks FROM grade_rules;

-- =========================
Salary Bands
-- =========================

-- 1. Create range type


CREATE TYPE salary_band AS RANGE (subtype = numeric);

-- 2. Table for jobs


CREATE TABLE jobs (
id SERIAL PRIMARY KEY,
title TEXT,
band salary_band
);

-- 3. Table for employees


CREATE TABLE employees (
eid SERIAL PRIMARY KEY,
name TEXT,
salary NUMERIC
);

-- 4. Sample data
INSERT INTO jobs (title, band) VALUES
('Junior Dev', '[30000, 50000)'),
('Mid Dev', '[50000, 80000)'),
('Senior Dev', '[80000, 120000)');

INSERT INTO employees (name, salary) VALUES


('Alice', 45000),
('Bob', 50000),
('Charlie', 90000);

-- 5. Queries
-- Jobs covering ₹50,000
SELECT * FROM jobs WHERE band @> 50000;

-- Employees whose salary falls within job band


SELECT e.name, e.salary, j.title
FROM employees e
JOIN jobs j ON j.band @> e.salary;

-- Raise lower bound by 10% for one job (e.g., Junior Dev)
UPDATE jobs
SET band = numrange(lower(band) * 1.1, upper(band))
WHERE title = 'Junior Dev';

Q5)

Date semesters • RANGE TYPE: semester AS RANGE (subtype = date)


• Table: academic_terms(code text pk, period semester)
• Queries: find term for DATE '2025-01-20'; list terms that overlap with Summer 2025;
ensure no overlaps via EXCLUDE constraint (extra): ALTER TABLE academic_terms ADD
CONSTRAINT no_overlap EXCLUDE USING gist (period WITH &&);

SOLUTION)

-- 1️⃣ Drop range type if already exists (avoid duplicate errors)


DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'semester')
THEN
DROP TYPE semester;
END IF;
END$$;

-- 2️⃣ Create range type


CREATE TYPE semester AS RANGE (subtype = date);

-- 3️⃣ Create table academic_terms


DROP TABLE IF EXISTS academic_terms CASCADE;

CREATE TABLE academic_terms (


code TEXT PRIMARY KEY,
period semester
);

-- 4️⃣ Insert sample data


INSERT INTO academic_terms (code, period) VALUES
('Spring 2025', '[2025-01-01,2025-05-15)'),
('Summer 2025', '[2025-05-15,2025-08-15)'),
('Fall 2025', '[2025-08-15,2025-12-31)');

-- 5️⃣ Query: Find term for specific date


SELECT code
FROM academic_terms
WHERE period @> DATE '2025-01-20';
-- 6️⃣ Query: List terms that overlap with Summer 2025
SELECT a1.code AS term, a2.code AS overlaps_with
FROM academic_terms a1
JOIN academic_terms a2
ON a1.period && a2.period
WHERE a1.code = 'Summer 2025'
AND a1.code <> a2.code;

-- 7️⃣ Add EXCLUDE constraint to avoid overlaps


ALTER TABLE academic_terms
ADD CONSTRAINT no_overlap
EXCLUDE USING gist (period WITH &&);

-- Test overlap prevention


-- This should fail because it overlaps with Summer 2025
INSERT INTO academic_terms (code, period)
VALUES ('Extra Term', '[2025-06-01,2025-07-01)');

You might also like