| 1 | -- noinspection SqlDialectInspectionForFile
|
|---|
| 2 |
|
|---|
| 3 | CREATE TABLE owner
|
|---|
| 4 | (
|
|---|
| 5 | id SERIAL NOT NULL,
|
|---|
| 6 | last_name varchar(255) NOT NULL,
|
|---|
| 7 | first_name varchar(255) NOT NULL,
|
|---|
| 8 | phone varchar(255),
|
|---|
| 9 | email varchar(255),
|
|---|
| 10 | address varchar(255),
|
|---|
| 11 | gender varchar(1) CHECK (gender IN ('M', 'F')),
|
|---|
| 12 | PRIMARY KEY (id)
|
|---|
| 13 | );
|
|---|
| 14 |
|
|---|
| 15 | CREATE TABLE pet
|
|---|
| 16 | (
|
|---|
| 17 | id SERIAL NOT NULL,
|
|---|
| 18 | name varchar(255) NOT NULL,
|
|---|
| 19 | is_active bool NOT NULL DEFAULT true,
|
|---|
| 20 | type varchar(255) CHECK (type IN ('mammal', 'bird', 'fish', 'amphibian', 'reptile')),
|
|---|
| 21 | breed varchar(255),
|
|---|
| 22 | age int4 CHECK (age >= 0),
|
|---|
| 23 | medical_history text,
|
|---|
| 24 | owner_id int4 NOT NULL,
|
|---|
| 25 | PRIMARY KEY (id),
|
|---|
| 26 | FOREIGN KEY (owner_id) REFERENCES owner (id)
|
|---|
| 27 | ON DELETE CASCADE
|
|---|
| 28 | ON UPDATE CASCADE
|
|---|
| 29 | );
|
|---|
| 30 |
|
|---|
| 31 | CREATE TABLE role
|
|---|
| 32 | (
|
|---|
| 33 | id SERIAL NOT NULL,
|
|---|
| 34 | name varchar(255) NOT NULL,
|
|---|
| 35 | description varchar(255),
|
|---|
| 36 | PRIMARY KEY (id)
|
|---|
| 37 | );
|
|---|
| 38 |
|
|---|
| 39 | CREATE TABLE employee
|
|---|
| 40 | (
|
|---|
| 41 | id SERIAL NOT NULL,
|
|---|
| 42 | last_name varchar(255) NOT NULL,
|
|---|
| 43 | first_name varchar(255) NOT NULL,
|
|---|
| 44 | phone varchar(255),
|
|---|
| 45 | email varchar(255),
|
|---|
| 46 | address varchar(255),
|
|---|
| 47 | date_employment date DEFAULT CURRENT_DATE,
|
|---|
| 48 | experience int4 DEFAULT 0 CHECK (experience >= 0),
|
|---|
| 49 | role_id int4,
|
|---|
| 50 | supervised_by int4,
|
|---|
| 51 | gender varchar(1) CHECK (gender IN ('M', 'F')),
|
|---|
| 52 | PRIMARY KEY (id),
|
|---|
| 53 | FOREIGN KEY (role_id) REFERENCES role (id)
|
|---|
| 54 | ON DELETE SET NULL
|
|---|
| 55 | ON UPDATE CASCADE,
|
|---|
| 56 | FOREIGN KEY (supervised_by) REFERENCES employee (id)
|
|---|
| 57 | ON DELETE SET NULL
|
|---|
| 58 | ON UPDATE CASCADE,
|
|---|
| 59 | CONSTRAINT check_not_self_supervisor CHECK (supervised_by != id)
|
|---|
| 60 | );
|
|---|
| 61 |
|
|---|
| 62 | CREATE TABLE appointment
|
|---|
| 63 | (
|
|---|
| 64 | id SERIAL NOT NULL,
|
|---|
| 65 | date_appointment date NOT NULL,
|
|---|
| 66 | reason varchar(255) NOT NULL,
|
|---|
| 67 | phone varchar(255),
|
|---|
| 68 | owner_id int4,
|
|---|
| 69 | pet_id int4,
|
|---|
| 70 | PRIMARY KEY (id),
|
|---|
| 71 | FOREIGN KEY (owner_id) REFERENCES owner (id)
|
|---|
| 72 | ON DELETE SET NULL
|
|---|
| 73 | ON UPDATE CASCADE,
|
|---|
| 74 | FOREIGN KEY (pet_id) REFERENCES pet (id)
|
|---|
| 75 | ON DELETE SET NULL
|
|---|
| 76 | ON UPDATE CASCADE
|
|---|
| 77 | );
|
|---|
| 78 |
|
|---|
| 79 | CREATE TABLE specialization
|
|---|
| 80 | (
|
|---|
| 81 | id SERIAL NOT NULL,
|
|---|
| 82 | specialization varchar(255) NOT NULL,
|
|---|
| 83 | license_number varchar(255) NOT NULL,
|
|---|
| 84 | employee_id int4 NOT NULL,
|
|---|
| 85 | PRIMARY KEY (id),
|
|---|
| 86 | FOREIGN KEY (employee_id) REFERENCES employee (id)
|
|---|
| 87 | ON DELETE CASCADE
|
|---|
| 88 | ON UPDATE CASCADE
|
|---|
| 89 | );
|
|---|
| 90 |
|
|---|
| 91 | CREATE TABLE certificate
|
|---|
| 92 | (
|
|---|
| 93 | id SERIAL NOT NULL,
|
|---|
| 94 | certificate_name varchar(255) NOT NULL,
|
|---|
| 95 | employee_id int4 NOT NULL,
|
|---|
| 96 | PRIMARY KEY (id),
|
|---|
| 97 | FOREIGN KEY (employee_id) REFERENCES employee (id)
|
|---|
| 98 | ON DELETE CASCADE
|
|---|
| 99 | ON UPDATE CASCADE
|
|---|
| 100 | );
|
|---|
| 101 |
|
|---|
| 102 | CREATE TABLE examination_room
|
|---|
| 103 | (
|
|---|
| 104 | id SERIAL NOT NULL,
|
|---|
| 105 | room_number varchar(255) NOT NULL,
|
|---|
| 106 | type varchar(255) NOT NULL CHECK (type IN
|
|---|
| 107 | ('examination', 'surgery', 'radiology', 'laboratory', 'isolation ward',
|
|---|
| 108 | 'patient ward')),
|
|---|
| 109 | capacity int4 CHECK (capacity > 0),
|
|---|
| 110 | status varchar(255) DEFAULT 'available' CHECK (status IN ('available', 'unavailable')),
|
|---|
| 111 | PRIMARY KEY (id)
|
|---|
| 112 | );
|
|---|
| 113 |
|
|---|
| 114 | CREATE TABLE examination
|
|---|
| 115 | (
|
|---|
| 116 | id SERIAL NOT NULL,
|
|---|
| 117 | date_examination date NOT NULL DEFAULT CURRENT_DATE,
|
|---|
| 118 | status varchar(255) NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'completed', 'cancelled')),
|
|---|
| 119 | description text,
|
|---|
| 120 | appointment_id int4,
|
|---|
| 121 | employee_id int4,
|
|---|
| 122 | examination_room_id int4,
|
|---|
| 123 | PRIMARY KEY (id),
|
|---|
| 124 | FOREIGN KEY (appointment_id) REFERENCES appointment (id)
|
|---|
| 125 | ON DELETE SET NULL
|
|---|
| 126 | ON UPDATE CASCADE,
|
|---|
| 127 | FOREIGN KEY (employee_id) REFERENCES employee (id)
|
|---|
| 128 | ON DELETE SET NULL
|
|---|
| 129 | ON UPDATE CASCADE,
|
|---|
| 130 | FOREIGN KEY (examination_room_id) REFERENCES examination_room (id)
|
|---|
| 131 | ON DELETE SET NULL
|
|---|
| 132 | ON UPDATE CASCADE
|
|---|
| 133 | );
|
|---|
| 134 |
|
|---|
| 135 | CREATE TABLE coupon
|
|---|
| 136 | (
|
|---|
| 137 | id SERIAL NOT NULL,
|
|---|
| 138 | code varchar(255) NOT NULL UNIQUE,
|
|---|
| 139 | type varchar(255) NOT NULL CHECK (type IN ('fixed', 'percentage')),
|
|---|
| 140 | value numeric(10, 2) NOT NULL CHECK (value >= 0),
|
|---|
| 141 | valid_from date NOT NULL DEFAULT CURRENT_DATE,
|
|---|
| 142 | valid_to date NOT NULL,
|
|---|
| 143 | usage_limit int4 NOT NULL DEFAULT 1,
|
|---|
| 144 | usage_count int4 NOT NULL DEFAULT 0,
|
|---|
| 145 | is_active bool NOT NULL DEFAULT true,
|
|---|
| 146 | min_total numeric(10, 2) DEFAULT 0 CHECK (min_total >= 0),
|
|---|
| 147 | PRIMARY KEY (id),
|
|---|
| 148 | CONSTRAINT check_dates CHECK (valid_to >= valid_from),
|
|---|
| 149 | CONSTRAINT check_usage CHECK (usage_limit >= 0 AND usage_count >= 0 AND usage_count <= usage_limit),
|
|---|
| 150 | CONSTRAINT check_percentage_value CHECK (
|
|---|
| 151 | type = 'fixed' OR (type = 'percentage' AND value <= 100)
|
|---|
| 152 | )
|
|---|
| 153 | );
|
|---|
| 154 |
|
|---|
| 155 | CREATE TABLE shop_item_category
|
|---|
| 156 | (
|
|---|
| 157 | id SERIAL NOT NULL,
|
|---|
| 158 | name varchar(255) NOT NULL,
|
|---|
| 159 | parent_id int4,
|
|---|
| 160 | PRIMARY KEY (id),
|
|---|
| 161 | FOREIGN KEY (parent_id) REFERENCES shop_item_category (id)
|
|---|
| 162 | ON DELETE SET NULL
|
|---|
| 163 | ON UPDATE CASCADE
|
|---|
| 164 | );
|
|---|
| 165 |
|
|---|
| 166 | CREATE TABLE shop_item
|
|---|
| 167 | (
|
|---|
| 168 | id SERIAL NOT NULL,
|
|---|
| 169 | name varchar(255) NOT NULL,
|
|---|
| 170 | price numeric(10, 2) NOT NULL CHECK (price >= 0),
|
|---|
| 171 | stock int4 DEFAULT 0 CHECK (stock >= 0),
|
|---|
| 172 | shop_item_category_id int4,
|
|---|
| 173 | PRIMARY KEY (id),
|
|---|
| 174 | FOREIGN KEY (shop_item_category_id) references shop_item_category (id)
|
|---|
| 175 | ON DELETE SET NULL
|
|---|
| 176 | ON UPDATE CASCADE
|
|---|
| 177 | );
|
|---|
| 178 |
|
|---|
| 179 | CREATE TABLE shop_item_attribute
|
|---|
| 180 | (
|
|---|
| 181 | id SERIAL NOT NULL,
|
|---|
| 182 | name varchar(255) NOT NULL,
|
|---|
| 183 | data_type varchar(255) NOT NULL CHECK (data_type IN ('text', 'integer', 'decimal', 'boolean', 'date')),
|
|---|
| 184 | shop_item_category_id int4 NOT NULL,
|
|---|
| 185 | PRIMARY KEY (id),
|
|---|
| 186 | FOREIGN KEY (shop_item_category_id) references shop_item_category (id)
|
|---|
| 187 | ON DELETE CASCADE
|
|---|
| 188 | ON UPDATE CASCADE
|
|---|
| 189 | );
|
|---|
| 190 |
|
|---|
| 191 | CREATE TABLE shop_item_attribute_value
|
|---|
| 192 | (
|
|---|
| 193 | id SERIAL NOT NULL,
|
|---|
| 194 | value varchar(255) NOT NULL,
|
|---|
| 195 | notes varchar(255),
|
|---|
| 196 | shop_item_attribute_id int4 NOT NULL,
|
|---|
| 197 | shop_item_id int4 NOT NULL,
|
|---|
| 198 | PRIMARY KEY (id),
|
|---|
| 199 | FOREIGN KEY (shop_item_attribute_id) references shop_item_attribute (id)
|
|---|
| 200 | ON DELETE CASCADE
|
|---|
| 201 | ON UPDATE CASCADE,
|
|---|
| 202 | FOREIGN KEY (shop_item_id) references shop_item (id)
|
|---|
| 203 | ON DELETE CASCADE
|
|---|
| 204 | ON UPDATE CASCADE
|
|---|
| 205 | );
|
|---|
| 206 |
|
|---|
| 207 | CREATE TABLE medicine
|
|---|
| 208 | (
|
|---|
| 209 | id SERIAL NOT NULL,
|
|---|
| 210 | name varchar(255) NOT NULL,
|
|---|
| 211 | manufacturer varchar(255),
|
|---|
| 212 | description varchar(255),
|
|---|
| 213 | shop_item_id int4,
|
|---|
| 214 | PRIMARY KEY (id),
|
|---|
| 215 | FOREIGN KEY (shop_item_id) REFERENCES shop_item (id)
|
|---|
| 216 | ON DELETE SET NULL
|
|---|
| 217 | ON UPDATE CASCADE
|
|---|
| 218 | );
|
|---|
| 219 |
|
|---|
| 220 | CREATE TABLE prescription
|
|---|
| 221 | (
|
|---|
| 222 | id SERIAL NOT NULL,
|
|---|
| 223 | examination_id int4 NOT NULL UNIQUE,
|
|---|
| 224 | date_start date NOT NULL,
|
|---|
| 225 | date_end date NOT NULL,
|
|---|
| 226 | description text,
|
|---|
| 227 | PRIMARY KEY (id),
|
|---|
| 228 | FOREIGN KEY (examination_id) REFERENCES examination (id)
|
|---|
| 229 | ON DELETE CASCADE
|
|---|
| 230 | ON UPDATE CASCADE,
|
|---|
| 231 | CONSTRAINT check_dates CHECK (date_end > date_start)
|
|---|
| 232 | );
|
|---|
| 233 |
|
|---|
| 234 | CREATE TABLE prescription_medicine
|
|---|
| 235 | (
|
|---|
| 236 | prescription_id int4 NOT NULL,
|
|---|
| 237 | medicine_id int4 NOT NULL,
|
|---|
| 238 | dosage int4 NOT NULL CHECK (dosage > 0),
|
|---|
| 239 | num_days int4 NOT NULL CHECK (num_days > 0),
|
|---|
| 240 | PRIMARY KEY (prescription_id, medicine_id),
|
|---|
| 241 | FOREIGN KEY (prescription_id) REFERENCES prescription (id)
|
|---|
| 242 | ON DELETE CASCADE
|
|---|
| 243 | ON UPDATE CASCADE,
|
|---|
| 244 | FOREIGN KEY (medicine_id) REFERENCES medicine (id)
|
|---|
| 245 | ON DELETE CASCADE
|
|---|
| 246 | ON UPDATE CASCADE
|
|---|
| 247 | );
|
|---|
| 248 |
|
|---|
| 249 | CREATE TABLE treatment_type
|
|---|
| 250 | (
|
|---|
| 251 | id SERIAL NOT NULL,
|
|---|
| 252 | name varchar(255) NOT NULL CHECK (name IN ('prescription', 'vaccination', 'consultation', 'operation')),
|
|---|
| 253 | PRIMARY KEY (id)
|
|---|
| 254 | );
|
|---|
| 255 |
|
|---|
| 256 | CREATE TABLE treatment
|
|---|
| 257 | (
|
|---|
| 258 | id SERIAL NOT NULL,
|
|---|
| 259 | date_treatment date NOT NULL DEFAULT CURRENT_DATE,
|
|---|
| 260 | notes text,
|
|---|
| 261 | treatment_type_id int4,
|
|---|
| 262 | examination_id int4,
|
|---|
| 263 | PRIMARY KEY (id),
|
|---|
| 264 | FOREIGN KEY (treatment_type_id) REFERENCES treatment_type (id)
|
|---|
| 265 | ON DELETE SET NULL
|
|---|
| 266 | ON UPDATE CASCADE,
|
|---|
| 267 | FOREIGN KEY (examination_id) REFERENCES examination (id)
|
|---|
| 268 | ON DELETE SET NULL
|
|---|
| 269 | ON UPDATE CASCADE
|
|---|
| 270 | );
|
|---|
| 271 |
|
|---|
| 272 | CREATE TABLE treatment_attribute
|
|---|
| 273 | (
|
|---|
| 274 | id SERIAL NOT NULL,
|
|---|
| 275 | name varchar(255) NOT NULL,
|
|---|
| 276 | data_type varchar(255) NOT NULL CHECK (data_type IN ('text', 'integer', 'decimal', 'boolean', 'date')),
|
|---|
| 277 | treatment_type_id int4 NOT NULL,
|
|---|
| 278 | PRIMARY KEY (id),
|
|---|
| 279 | FOREIGN KEY (treatment_type_id) references treatment_type (id)
|
|---|
| 280 | ON DELETE CASCADE
|
|---|
| 281 | ON UPDATE CASCADE
|
|---|
| 282 | );
|
|---|
| 283 |
|
|---|
| 284 | CREATE TABLE treatment_attribute_value
|
|---|
| 285 | (
|
|---|
| 286 | id SERIAL NOT NULL,
|
|---|
| 287 | value varchar(255) NOT NULL,
|
|---|
| 288 | notes varchar(255),
|
|---|
| 289 | treatment_attribute_id int4 NOT NULL,
|
|---|
| 290 | treatment_id int4 NOT NULL,
|
|---|
| 291 | PRIMARY KEY (id),
|
|---|
| 292 | FOREIGN KEY (treatment_attribute_id) references treatment_attribute (id)
|
|---|
| 293 | ON DELETE CASCADE
|
|---|
| 294 | ON UPDATE CASCADE,
|
|---|
| 295 | FOREIGN KEY (treatment_id) references treatment (id)
|
|---|
| 296 | ON DELETE CASCADE
|
|---|
| 297 | ON UPDATE CASCADE
|
|---|
| 298 | );
|
|---|
| 299 |
|
|---|
| 300 | CREATE TABLE discount
|
|---|
| 301 | (
|
|---|
| 302 | id SERIAL NOT NULL,
|
|---|
| 303 | type varchar(255) NOT NULL CHECK (type IN ('fixed', 'percentage')),
|
|---|
| 304 | value numeric(10, 2) NOT NULL CHECK (value >= 0),
|
|---|
| 305 | description varchar(255),
|
|---|
| 306 | date_from date DEFAULT CURRENT_DATE,
|
|---|
| 307 | date_to date,
|
|---|
| 308 | shop_item_id int4,
|
|---|
| 309 | PRIMARY KEY (id),
|
|---|
| 310 | FOREIGN KEY (shop_item_id) REFERENCES shop_item (id)
|
|---|
| 311 | ON DELETE SET NULL
|
|---|
| 312 | ON UPDATE CASCADE,
|
|---|
| 313 | CONSTRAINT check_dates CHECK (date_to > date_from)
|
|---|
| 314 | );
|
|---|
| 315 |
|
|---|
| 316 | CREATE TABLE invoice
|
|---|
| 317 | (
|
|---|
| 318 | id SERIAL NOT NULL,
|
|---|
| 319 | date_invoice date NOT NULL DEFAULT CURRENT_DATE,
|
|---|
| 320 | total numeric(10, 2) NOT NULL CHECK (total >= 0),
|
|---|
| 321 | coupon_id int4,
|
|---|
| 322 | owner_id int4,
|
|---|
| 323 | PRIMARY KEY (id),
|
|---|
| 324 | FOREIGN KEY (coupon_id) REFERENCES coupon (id)
|
|---|
| 325 | ON DELETE SET NULL
|
|---|
| 326 | ON UPDATE CASCADE,
|
|---|
| 327 | FOREIGN KEY (owner_id) REFERENCES owner (id)
|
|---|
| 328 | ON DELETE SET NULL
|
|---|
| 329 | ON UPDATE CASCADE
|
|---|
| 330 | );
|
|---|
| 331 |
|
|---|
| 332 | CREATE TABLE invoice_item
|
|---|
| 333 | (
|
|---|
| 334 | num_item int4 NOT NULL CHECK (num_item > 0),
|
|---|
| 335 | invoice_id int4 NOT NULL,
|
|---|
| 336 | price numeric(10, 2) NOT NULL CHECK (price >= 0),
|
|---|
| 337 | quantity int4 NOT NULL DEFAULT 1 CHECK (quantity >= 0),
|
|---|
| 338 | type varchar(255) CHECK (type IN ('shop_item', 'treatment')),
|
|---|
| 339 | shop_item_id int4,
|
|---|
| 340 | treatment_id int4,
|
|---|
| 341 | PRIMARY KEY (num_item, invoice_id),
|
|---|
| 342 | FOREIGN KEY (invoice_id) REFERENCES invoice (id)
|
|---|
| 343 | ON DELETE CASCADE
|
|---|
| 344 | ON UPDATE CASCADE,
|
|---|
| 345 | FOREIGN KEY (shop_item_id) REFERENCES shop_item (id)
|
|---|
| 346 | ON DELETE SET NULL
|
|---|
| 347 | ON UPDATE CASCADE,
|
|---|
| 348 | FOREIGN KEY (treatment_id) REFERENCES treatment (id)
|
|---|
| 349 | ON DELETE SET NULL
|
|---|
| 350 | ON UPDATE CASCADE,
|
|---|
| 351 | CONSTRAINT check_type CHECK (
|
|---|
| 352 | (type = 'shop_item' AND shop_item_id IS NOT NULL AND treatment_id IS NULL) OR
|
|---|
| 353 | (type = 'treatment' AND treatment_id IS NOT NULL AND shop_item_id IS NULL)
|
|---|
| 354 | )
|
|---|
| 355 | );
|
|---|
| 356 |
|
|---|
| 357 | CREATE TABLE payment
|
|---|
| 358 | (
|
|---|
| 359 | id SERIAL NOT NULL,
|
|---|
| 360 | date_payment date NOT NULL DEFAULT CURRENT_DATE,
|
|---|
| 361 | amount numeric(10, 2) NOT NULL CHECK (amount >= 0),
|
|---|
| 362 | method varchar(255) NOT NULL CHECK (method IN
|
|---|
| 363 | ('cash', 'debit card', 'credit card', 'digital wallet', 'other')),
|
|---|
| 364 | invoice_id int4 NOT NULL,
|
|---|
| 365 | PRIMARY KEY (id),
|
|---|
| 366 | FOREIGN KEY (invoice_id) REFERENCES invoice (id)
|
|---|
| 367 | ON DELETE CASCADE
|
|---|
| 368 | ON UPDATE CASCADE
|
|---|
| 369 | );
|
|---|
| 370 |
|
|---|
| 371 | -- ===============================
|
|---|
| 372 | -- composite primary key in invoice_item (num_item, invoice_id)
|
|---|
| 373 | -- ===============================
|
|---|
| 374 | CREATE OR REPLACE FUNCTION generate_num_item()
|
|---|
| 375 | RETURNS TRIGGER AS
|
|---|
| 376 | $$
|
|---|
| 377 | BEGIN
|
|---|
| 378 | SELECT COALESCE(MAX(num_item), 0) + 1
|
|---|
| 379 | INTO NEW.num_item
|
|---|
| 380 | FROM invoice_item
|
|---|
| 381 | WHERE invoice_id = NEW.invoice_id;
|
|---|
| 382 | RETURN NEW;
|
|---|
| 383 | END;
|
|---|
| 384 | $$ LANGUAGE plpgsql;
|
|---|
| 385 |
|
|---|
| 386 | CREATE TRIGGER trg_generate_num_item
|
|---|
| 387 | BEFORE INSERT
|
|---|
| 388 | ON invoice_item
|
|---|
| 389 | FOR EACH ROW
|
|---|
| 390 | EXECUTE FUNCTION generate_num_item();
|
|---|
| 391 |
|
|---|
| 392 |
|
|---|
| 393 |
|
|---|
| 394 | -- DROP SCHEMA public CASCADE;
|
|---|
| 395 | -- CREATE SCHEMA public;
|
|---|
| 396 |
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 |
|
|---|
| 400 | -- temp tables for names, surnames and addresses
|
|---|
| 401 | create table temp_male_names
|
|---|
| 402 | (
|
|---|
| 403 | id bigserial primary key,
|
|---|
| 404 | year int4,
|
|---|
| 405 | name text,
|
|---|
| 406 | count int4
|
|---|
| 407 | );
|
|---|
| 408 |
|
|---|
| 409 | SHOW data_directory;
|
|---|
| 410 |
|
|---|
| 411 | COPY temp_male_names (year, name, count) FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/baby_names_-_male.csv' DELIMITER ',' CSV HEADER;
|
|---|
| 412 | UPDATE temp_male_names
|
|---|
| 413 | SET name = TRIM(name);
|
|---|
| 414 |
|
|---|
| 415 | create table temp_female_names
|
|---|
| 416 | (
|
|---|
| 417 | id bigserial primary key,
|
|---|
| 418 | year int4,
|
|---|
| 419 | name text,
|
|---|
| 420 | count int4
|
|---|
| 421 | );
|
|---|
| 422 |
|
|---|
| 423 | COPY temp_female_names (year, name, count) FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/baby_names_-_female_.csv' DELIMITER ',' CSV HEADER;
|
|---|
| 424 | UPDATE temp_female_names
|
|---|
| 425 | SET name = TRIM(name);
|
|---|
| 426 |
|
|---|
| 427 | create table temp_surnames
|
|---|
| 428 | (
|
|---|
| 429 | id bigserial primary key,
|
|---|
| 430 | year int4,
|
|---|
| 431 | rank text,
|
|---|
| 432 | surname text,
|
|---|
| 433 | number int4
|
|---|
| 434 | );
|
|---|
| 435 |
|
|---|
| 436 | COPY temp_surnames (year, rank, surname, number) FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/surnames.csv' DELIMITER ',' CSV HEADER;
|
|---|
| 437 | UPDATE temp_surnames
|
|---|
| 438 | SET surname = TRIM(surname);
|
|---|
| 439 |
|
|---|
| 440 | CREATE TABLE temp_addresses
|
|---|
| 441 | (
|
|---|
| 442 | id bigserial primary key,
|
|---|
| 443 | address text,
|
|---|
| 444 | city text,
|
|---|
| 445 | state text,
|
|---|
| 446 | zip text
|
|---|
| 447 | );
|
|---|
| 448 |
|
|---|
| 449 | COPY temp_addresses (address, city, state, zip) FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/addresses.csv' DELIMITER ',' CSV HEADER;
|
|---|
| 450 | UPDATE temp_addresses
|
|---|
| 451 | SET address = TRIM(address);
|
|---|
| 452 | UPDATE temp_addresses
|
|---|
| 453 | SET city = TRIM(city);
|
|---|
| 454 | UPDATE temp_addresses
|
|---|
| 455 | SET state = TRIM(state);
|
|---|
| 456 | UPDATE temp_addresses
|
|---|
| 457 | SET zip = TRIM(zip);
|
|---|
| 458 |
|
|---|
| 459 |
|
|---|
| 460 | -- ============================================================
|
|---|
| 461 | -- role
|
|---|
| 462 | -- ============================================================
|
|---|
| 463 |
|
|---|
| 464 | INSERT INTO role (name, description)
|
|---|
| 465 | VALUES ('Manager', 'Oversees clinic operations'),
|
|---|
| 466 | ('Veterinarian', 'Licensed veterinarian responsible for examinations and treatments'),
|
|---|
| 467 | ('Veterinary Assistant', 'Assists veterinarians during procedures'),
|
|---|
| 468 | ('Receptionist', 'Handles appointments and client communication');
|
|---|
| 469 |
|
|---|
| 470 | -- ============================================================
|
|---|
| 471 | -- employee
|
|---|
| 472 | -- (50 employees: 1 manager, 9 doctors, 35 vet assistants, 5 receptionists)
|
|---|
| 473 | -- ============================================================
|
|---|
| 474 |
|
|---|
| 475 | WITH male_names_sample AS (SELECT name
|
|---|
| 476 | FROM temp_male_names
|
|---|
| 477 | ORDER BY random()
|
|---|
| 478 | LIMIT 1000),
|
|---|
| 479 | female_names_sample AS (SELECT name
|
|---|
| 480 | FROM temp_female_names
|
|---|
| 481 | ORDER BY random()
|
|---|
| 482 | LIMIT 1000),
|
|---|
| 483 | male_pool AS (SELECT fn.name AS first_name,
|
|---|
| 484 | ln.surname AS last_name,
|
|---|
| 485 | 'M' AS gender
|
|---|
| 486 | FROM male_names_sample fn
|
|---|
| 487 | CROSS JOIN temp_surnames ln
|
|---|
| 488 | ORDER BY random()
|
|---|
| 489 | LIMIT 25),
|
|---|
| 490 | female_pool AS (SELECT fn.name AS first_name,
|
|---|
| 491 | ln.surname AS last_name,
|
|---|
| 492 | 'F' AS gender
|
|---|
| 493 | FROM female_names_sample fn
|
|---|
| 494 | CROSS JOIN temp_surnames ln
|
|---|
| 495 | ORDER BY random()
|
|---|
| 496 | LIMIT 25),
|
|---|
| 497 | all_names AS (SELECT first_name, last_name, gender
|
|---|
| 498 | FROM male_pool
|
|---|
| 499 | UNION ALL
|
|---|
| 500 | SELECT first_name, last_name, gender
|
|---|
| 501 | FROM female_pool),
|
|---|
| 502 | numbered AS (SELECT first_name,
|
|---|
| 503 | last_name,
|
|---|
| 504 | gender,
|
|---|
| 505 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 506 | FROM all_names),
|
|---|
| 507 | shuffled_addresses AS (SELECT address || ', ' || city || ', ' || state || ' ' || zip AS full_address,
|
|---|
| 508 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 509 | FROM temp_addresses),
|
|---|
| 510 | shuffled_phones AS (SELECT ((row_number() OVER (ORDER BY random()) % 9) + 1)::text AS d1,
|
|---|
| 511 | lpad(((row_number() OVER (ORDER BY random()) * 73) % 900 + 100)::text, 3, '0') AS d2,
|
|---|
| 512 | lpad(((row_number() OVER (ORDER BY random()) * 97) % 900 + 100)::text, 3, '0') AS d3,
|
|---|
| 513 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 514 | FROM generate_series(1, 50))
|
|---|
| 515 | INSERT
|
|---|
| 516 | INTO employee (first_name, last_name, phone, email, address, gender, date_employment, role_id, supervised_by)
|
|---|
| 517 | SELECT n.first_name,
|
|---|
| 518 | n.last_name,
|
|---|
| 519 | '+389 7' || p.d1 || ' ' || p.d2 || ' ' || p.d3 AS phone,
|
|---|
| 520 | lower(n.first_name) || '.' || lower(n.last_name) || '@pawcare.com' AS email,
|
|---|
| 521 | a.full_address AS address,
|
|---|
| 522 | n.gender,
|
|---|
| 523 | (now() - interval '1 day' * floor(random() * 3650))::date AS date_employment,
|
|---|
| 524 | CASE
|
|---|
| 525 | WHEN n.rn = 1 THEN 1 -- manager
|
|---|
| 526 | WHEN n.rn <= 10 THEN 2 -- veterinarians
|
|---|
| 527 | WHEN n.rn <= 45 THEN 3 -- vet assistants (rn 11-45 = 35 employees)
|
|---|
| 528 | ELSE 4 -- receptionists (rn 46-50 = 5 employees)
|
|---|
| 529 | END AS role_id,
|
|---|
| 530 | NULL AS supervised_by
|
|---|
| 531 | FROM numbered n
|
|---|
| 532 | JOIN shuffled_phones p ON p.rn = n.rn
|
|---|
| 533 | JOIN shuffled_addresses a ON a.rn = n.rn
|
|---|
| 534 | ORDER BY n.rn;
|
|---|
| 535 |
|
|---|
| 536 | -- experience for all employees: at least years since employment
|
|---|
| 537 | UPDATE employee
|
|---|
| 538 | SET experience = (
|
|---|
| 539 | extract(year from age(now(), date_employment))
|
|---|
| 540 | + floor(random() * 5)
|
|---|
| 541 | )::int
|
|---|
| 542 | WHERE role_id IN (3, 4); -- vet assistants and receptionists: 0-5 extra years
|
|---|
| 543 |
|
|---|
| 544 | -- vets get more experience
|
|---|
| 545 | UPDATE employee
|
|---|
| 546 | SET experience = (
|
|---|
| 547 | extract(year from age(now(), date_employment))
|
|---|
| 548 | + floor(random() * 15) + 5
|
|---|
| 549 | )::int
|
|---|
| 550 | WHERE role_id = 2; -- veterinarians: at least 5 extra years on top
|
|---|
| 551 |
|
|---|
| 552 | -- manager gets more experience
|
|---|
| 553 | UPDATE employee
|
|---|
| 554 | SET experience = (
|
|---|
| 555 | extract(year from age(now(), date_employment))
|
|---|
| 556 | + floor(random() * 10) + 8
|
|---|
| 557 | )::int
|
|---|
| 558 | WHERE role_id = 1;
|
|---|
| 559 |
|
|---|
| 560 | -- supervised_by updates
|
|---|
| 561 | UPDATE employee
|
|---|
| 562 | SET supervised_by = 1
|
|---|
| 563 | WHERE role_id = 2; -- for doctors: manager
|
|---|
| 564 |
|
|---|
| 565 | UPDATE employee
|
|---|
| 566 | SET supervised_by = (floor(random() * 9) + 2)::int
|
|---|
| 567 | WHERE role_id = 3; -- for vet assistants: random doctor (ids 2-10)
|
|---|
| 568 |
|
|---|
| 569 | UPDATE employee
|
|---|
| 570 | SET supervised_by = 1
|
|---|
| 571 | WHERE role_id = 4; -- for receptionists: manager
|
|---|
| 572 |
|
|---|
| 573 | -- ============================================================
|
|---|
| 574 | -- owner
|
|---|
| 575 | -- 400 owners
|
|---|
| 576 | -- ============================================================
|
|---|
| 577 |
|
|---|
| 578 | WITH male_names_sample AS (SELECT name
|
|---|
| 579 | FROM temp_male_names
|
|---|
| 580 | ORDER BY random()
|
|---|
| 581 | LIMIT 2000),
|
|---|
| 582 | female_names_sample AS (SELECT name
|
|---|
| 583 | FROM temp_female_names
|
|---|
| 584 | ORDER BY random()
|
|---|
| 585 | LIMIT 2000),
|
|---|
| 586 | male_pool AS (SELECT fn.name AS first_name,
|
|---|
| 587 | ln.surname AS last_name,
|
|---|
| 588 | 'M' AS gender
|
|---|
| 589 | FROM male_names_sample fn
|
|---|
| 590 | CROSS JOIN temp_surnames ln
|
|---|
| 591 | ORDER BY random()),
|
|---|
| 592 | female_pool AS (SELECT fn.name AS first_name,
|
|---|
| 593 | ln.surname AS last_name,
|
|---|
| 594 | 'F' AS gender
|
|---|
| 595 | FROM female_names_sample fn
|
|---|
| 596 | CROSS JOIN temp_surnames ln
|
|---|
| 597 | ORDER BY random()),
|
|---|
| 598 | all_names AS (SELECT first_name, last_name, gender
|
|---|
| 599 | FROM male_pool
|
|---|
| 600 | UNION ALL
|
|---|
| 601 | SELECT first_name, last_name, gender
|
|---|
| 602 | FROM female_pool),
|
|---|
| 603 | numbered AS (SELECT first_name,
|
|---|
| 604 | last_name,
|
|---|
| 605 | gender,
|
|---|
| 606 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 607 | FROM all_names),
|
|---|
| 608 | shuffled_addresses AS (SELECT address || ', ' || city || ', ' || state || ' ' || zip AS full_address,
|
|---|
| 609 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 610 | FROM temp_addresses),
|
|---|
| 611 | shuffled_phones AS (SELECT ((row_number() OVER (ORDER BY random()) % 9) + 1)::text AS d1,
|
|---|
| 612 | lpad(((row_number() OVER (ORDER BY random()) * 73) % 900 + 100)::text, 3, '0') AS d2,
|
|---|
| 613 | lpad(((row_number() OVER (ORDER BY random()) * 97) % 900 + 100)::text, 3, '0') AS d3,
|
|---|
| 614 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 615 | FROM generate_series(1, 400))
|
|---|
| 616 | INSERT
|
|---|
| 617 | INTO owner (first_name, last_name, phone, email, address, gender)
|
|---|
| 618 | SELECT n.first_name,
|
|---|
| 619 | n.last_name,
|
|---|
| 620 | '+389 7' || p.d1 || ' ' || p.d2 || ' ' || p.d3 AS phone,
|
|---|
| 621 | lower(n.first_name) || '.' || lower(n.last_name) || '@gmail.com' AS email,
|
|---|
| 622 | a.full_address AS address,
|
|---|
| 623 | n.gender
|
|---|
| 624 | FROM numbered n
|
|---|
| 625 | JOIN shuffled_phones p ON p.rn = n.rn
|
|---|
| 626 | JOIN shuffled_addresses a ON a.rn = ((n.rn - 1) % (SELECT count(*) FROM temp_addresses) + 1)
|
|---|
| 627 | ORDER BY random()
|
|---|
| 628 | LIMIT 400;
|
|---|
| 629 |
|
|---|
| 630 | -- contraint for email and phone on owner and employee:
|
|---|
| 631 | ALTER TABLE owner
|
|---|
| 632 | ADD CONSTRAINT check_email
|
|---|
| 633 | CHECK (email ~* '^[^@\s]+\.[^@\s]+@[^@\s]+\.[^@\s]+$'),
|
|---|
| 634 | ADD CONSTRAINT check_phone
|
|---|
| 635 | CHECK (phone ~ '^\+389 7[0-9] [0-9]{3} [0-9]{3}$');
|
|---|
| 636 |
|
|---|
| 637 | ALTER TABLE employee
|
|---|
| 638 | ADD CONSTRAINT check_email
|
|---|
| 639 | CHECK (email ~* '^[^@\s]+\.[^@\s]+@[^@\s]+\.[^@\s]+$'),
|
|---|
| 640 | ADD CONSTRAINT check_phone
|
|---|
| 641 | CHECK (phone ~ '^\+389 7[0-9] [0-9]{3} [0-9]{3}$');
|
|---|
| 642 |
|
|---|
| 643 |
|
|---|
| 644 |
|
|---|
| 645 |
|
|---|
| 646 | -- -- fix for foreign key in medicine (Small flaw)
|
|---|
| 647 | --
|
|---|
| 648 | -- ALTER TABLE medicine
|
|---|
| 649 | -- DROP CONSTRAINT IF EXISTS medicine_shop_item_id_fkey;
|
|---|
| 650 | --
|
|---|
| 651 | -- ALTER TABLE medicine
|
|---|
| 652 | -- ADD CONSTRAINT medicine_shop_item_id_fkey
|
|---|
| 653 | -- FOREIGN KEY (shop_item_id) REFERENCES shop_item (id)
|
|---|
| 654 | -- ON DELETE SET NULL
|
|---|
| 655 | -- ON UPDATE CASCADE;
|
|---|
| 656 |
|
|---|
| 657 |
|
|---|
| 658 | -- fix for foreign key in invoice_item
|
|---|
| 659 |
|
|---|
| 660 | -- ALTER TABLE invoice_item
|
|---|
| 661 | -- DROP CONSTRAINT IF EXISTS check_type;
|
|---|
| 662 | --
|
|---|
| 663 | -- ALTER TABLE invoice_item
|
|---|
| 664 | -- ADD CONSTRAINT check_type
|
|---|
| 665 | -- CHECK (
|
|---|
| 666 | -- (type = 'shop_item' AND shop_item_id IS NOT NULL AND treatment_id IS NULL) OR
|
|---|
| 667 | -- (type = 'treatment' AND treatment_id IS NOT NULL AND shop_item_id IS NULL)
|
|---|
| 668 | -- );
|
|---|
| 669 |
|
|---|
| 670 | -- unique coupon code
|
|---|
| 671 |
|
|---|
| 672 | -- ALTER TABLE coupon
|
|---|
| 673 | -- ADD CONSTRAINT unique_coupon_code UNIQUE (code);
|
|---|
| 674 |
|
|---|
| 675 | -- fix for usage_limit in coupon
|
|---|
| 676 |
|
|---|
| 677 | -- ALTER TABLE coupon
|
|---|
| 678 | -- DROP CONSTRAINT IF EXISTS check_usage;
|
|---|
| 679 | --
|
|---|
| 680 | -- ALTER TABLE coupon
|
|---|
| 681 | -- ADD CONSTRAINT check_usage
|
|---|
| 682 | -- CHECK (
|
|---|
| 683 | -- usage_limit > 0 AND
|
|---|
| 684 | -- usage_count >= 0 AND
|
|---|
| 685 | -- usage_count <= usage_limit
|
|---|
| 686 | -- );
|
|---|
| 687 |
|
|---|
| 688 |
|
|---|
| 689 | -- small fixes in owner
|
|---|
| 690 |
|
|---|
| 691 | ALTER TABLE owner
|
|---|
| 692 | ADD CONSTRAINT unique_owner_email UNIQUE (email);
|
|---|
| 693 |
|
|---|
| 694 | ALTER TABLE employee
|
|---|
| 695 | ADD CONSTRAINT unique_employee_email UNIQUE (email);
|
|---|
| 696 |
|
|---|
| 697 | ALTER TABLE owner
|
|---|
| 698 | ALTER COLUMN email SET NOT NULL;
|
|---|
| 699 |
|
|---|
| 700 | ALTER TABLE employee
|
|---|
| 701 | ALTER COLUMN email SET NOT NULL;
|
|---|
| 702 |
|
|---|
| 703 |
|
|---|
| 704 | -- ============================================================
|
|---|
| 705 | -- pet
|
|---|
| 706 | -- ============================================================
|
|---|
| 707 |
|
|---|
| 708 |
|
|---|
| 709 | CREATE TABLE temp_breeds_mammal (
|
|---|
| 710 | id bigserial primary key,
|
|---|
| 711 | breed_name text
|
|---|
| 712 | );
|
|---|
| 713 |
|
|---|
| 714 | CREATE TABLE temp_breeds_bird (
|
|---|
| 715 | id bigserial primary key,
|
|---|
| 716 | breed_name text
|
|---|
| 717 | );
|
|---|
| 718 |
|
|---|
| 719 | CREATE TABLE temp_breeds_fish (
|
|---|
| 720 | id bigserial primary key,
|
|---|
| 721 | breed_name text
|
|---|
| 722 | );
|
|---|
| 723 |
|
|---|
| 724 | CREATE TABLE temp_breeds_amphibian (
|
|---|
| 725 | id bigserial primary key,
|
|---|
| 726 | breed_name text
|
|---|
| 727 | );
|
|---|
| 728 |
|
|---|
| 729 | CREATE TABLE temp_breeds_reptile (
|
|---|
| 730 | id bigserial primary key,
|
|---|
| 731 | breed_name text
|
|---|
| 732 | );
|
|---|
| 733 |
|
|---|
| 734 | CREATE TABLE temp_pet_names (
|
|---|
| 735 | id bigserial primary key,
|
|---|
| 736 | name text
|
|---|
| 737 | );
|
|---|
| 738 |
|
|---|
| 739 | CREATE TABLE temp_medical_history (
|
|---|
| 740 | id bigserial primary key,
|
|---|
| 741 | history text
|
|---|
| 742 | );
|
|---|
| 743 |
|
|---|
| 744 | COPY temp_breeds_mammal (breed_name)
|
|---|
| 745 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/mammal_pet_breeds.csv'
|
|---|
| 746 | DELIMITER ',' CSV HEADER;
|
|---|
| 747 |
|
|---|
| 748 | COPY temp_breeds_bird (breed_name)
|
|---|
| 749 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_birds.csv'
|
|---|
| 750 | DELIMITER ',' CSV HEADER;
|
|---|
| 751 |
|
|---|
| 752 | COPY temp_breeds_fish (breed_name)
|
|---|
| 753 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_fish_breeds.csv'
|
|---|
| 754 | DELIMITER ',' CSV HEADER;
|
|---|
| 755 |
|
|---|
| 756 | COPY temp_breeds_amphibian (breed_name)
|
|---|
| 757 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_amphibians.csv'
|
|---|
| 758 | DELIMITER ',' CSV HEADER;
|
|---|
| 759 |
|
|---|
| 760 | COPY temp_breeds_reptile (breed_name)
|
|---|
| 761 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_reptiles.csv'
|
|---|
| 762 | DELIMITER ',' CSV HEADER;
|
|---|
| 763 |
|
|---|
| 764 | COPY temp_pet_names (name)
|
|---|
| 765 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_names.csv'
|
|---|
| 766 | DELIMITER ',' CSV HEADER;
|
|---|
| 767 |
|
|---|
| 768 | COPY temp_medical_history (history)
|
|---|
| 769 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_medical_history.csv'
|
|---|
| 770 | DELIMITER ',' CSV HEADER;
|
|---|
| 771 |
|
|---|
| 772 |
|
|---|
| 773 | --altering column age for pet (so it works for both months and years)
|
|---|
| 774 |
|
|---|
| 775 | -- ALTER TABLE pet
|
|---|
| 776 | -- ALTER COLUMN age TYPE int4;
|
|---|
| 777 |
|
|---|
| 778 | ALTER TABLE pet
|
|---|
| 779 | ADD COLUMN age_display text GENERATED ALWAYS AS (
|
|---|
| 780 | CASE
|
|---|
| 781 | WHEN age IS NULL THEN 'Unknown'
|
|---|
| 782 | WHEN age < 12 THEN age || ' months'
|
|---|
| 783 | WHEN age < 24 THEN '1 year'
|
|---|
| 784 | ELSE (age / 12) || ' years'
|
|---|
| 785 | END
|
|---|
| 786 | ) STORED;
|
|---|
| 787 |
|
|---|
| 788 |
|
|---|
| 789 | WITH base AS (
|
|---|
| 790 | SELECT generate_series(1, 700) AS rn
|
|---|
| 791 | ),
|
|---|
| 792 |
|
|---|
| 793 | typed AS (
|
|---|
| 794 | SELECT
|
|---|
| 795 | rn,
|
|---|
| 796 | CASE
|
|---|
| 797 | WHEN r < 0.60 THEN 'mammal'
|
|---|
| 798 | WHEN r < 0.70 THEN 'bird'
|
|---|
| 799 | WHEN r < 0.80 THEN 'reptile'
|
|---|
| 800 | WHEN r < 0.90 THEN 'fish'
|
|---|
| 801 | ELSE 'amphibian'
|
|---|
| 802 | END AS type
|
|---|
| 803 | FROM (
|
|---|
| 804 | SELECT rn, random() AS r
|
|---|
| 805 | FROM base
|
|---|
| 806 | ) x
|
|---|
| 807 | ),
|
|---|
| 808 |
|
|---|
| 809 | breed_counts AS (
|
|---|
| 810 | SELECT
|
|---|
| 811 | (SELECT count(*) FROM temp_breeds_mammal) AS mammal_cnt,
|
|---|
| 812 | (SELECT count(*) FROM temp_breeds_bird) AS bird_cnt,
|
|---|
| 813 | (SELECT count(*) FROM temp_breeds_fish) AS fish_cnt,
|
|---|
| 814 | (SELECT count(*) FROM temp_breeds_reptile) AS reptile_cnt,
|
|---|
| 815 | (SELECT count(*) FROM temp_breeds_amphibian) AS amphibian_cnt,
|
|---|
| 816 | (SELECT count(*) FROM temp_pet_names) AS names_cnt,
|
|---|
| 817 | (SELECT count(*) FROM temp_medical_history) AS history_cnt
|
|---|
| 818 | ),
|
|---|
| 819 |
|
|---|
| 820 | owner_pool AS (
|
|---|
| 821 | SELECT
|
|---|
| 822 | id,
|
|---|
| 823 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 824 | FROM owner
|
|---|
| 825 | ),
|
|---|
| 826 |
|
|---|
| 827 | owner_counts AS (
|
|---|
| 828 | SELECT count(*) AS cnt FROM owner
|
|---|
| 829 | ),
|
|---|
| 830 |
|
|---|
| 831 | names AS (
|
|---|
| 832 | SELECT name, row_number() OVER () AS rn
|
|---|
| 833 | FROM (SELECT name FROM temp_pet_names ORDER BY random()) t
|
|---|
| 834 | ),
|
|---|
| 835 |
|
|---|
| 836 | history AS (
|
|---|
| 837 | SELECT history, row_number() OVER () AS rn
|
|---|
| 838 | FROM (SELECT history FROM temp_medical_history ORDER BY random()) t
|
|---|
| 839 | ),
|
|---|
| 840 |
|
|---|
| 841 | mammal_breeds AS (
|
|---|
| 842 | SELECT breed_name, row_number() OVER () AS rn
|
|---|
| 843 | FROM (SELECT breed_name FROM temp_breeds_mammal ORDER BY random()) t
|
|---|
| 844 | ),
|
|---|
| 845 |
|
|---|
| 846 | bird_breeds AS (
|
|---|
| 847 | SELECT breed_name, row_number() OVER () AS rn
|
|---|
| 848 | FROM (SELECT breed_name FROM temp_breeds_bird ORDER BY random()) t
|
|---|
| 849 | ),
|
|---|
| 850 |
|
|---|
| 851 | fish_breeds AS (
|
|---|
| 852 | SELECT breed_name, row_number() OVER () AS rn
|
|---|
| 853 | FROM (SELECT breed_name FROM temp_breeds_fish ORDER BY random()) t
|
|---|
| 854 | ),
|
|---|
| 855 |
|
|---|
| 856 | reptile_breeds AS (
|
|---|
| 857 | SELECT breed_name, row_number() OVER () AS rn
|
|---|
| 858 | FROM (SELECT breed_name FROM temp_breeds_reptile ORDER BY random()) t
|
|---|
| 859 | ),
|
|---|
| 860 |
|
|---|
| 861 | amphibian_breeds AS (
|
|---|
| 862 | SELECT breed_name, row_number() OVER () AS rn
|
|---|
| 863 | FROM (SELECT breed_name FROM temp_breeds_amphibian ORDER BY random()) t
|
|---|
| 864 | ),
|
|---|
| 865 |
|
|---|
| 866 | owner_assignment AS (
|
|---|
| 867 | SELECT
|
|---|
| 868 | t.rn AS pet_rn,
|
|---|
| 869 | CASE
|
|---|
| 870 | WHEN t.rn <= 400
|
|---|
| 871 | THEN (SELECT id FROM owner_pool op WHERE op.rn = t.rn)
|
|---|
| 872 | ELSE
|
|---|
| 873 | (SELECT id FROM owner_pool op
|
|---|
| 874 | WHERE op.rn = (abs(hashtext('owner_' || t.rn)) % (SELECT cnt FROM owner_counts)) + 1)
|
|---|
| 875 | END AS owner_id
|
|---|
| 876 | FROM typed t
|
|---|
| 877 | )
|
|---|
| 878 |
|
|---|
| 879 | INSERT INTO pet (
|
|---|
| 880 | name,
|
|---|
| 881 | is_active,
|
|---|
| 882 | type,
|
|---|
| 883 | breed,
|
|---|
| 884 | age,
|
|---|
| 885 | medical_history,
|
|---|
| 886 | owner_id
|
|---|
| 887 | )
|
|---|
| 888 |
|
|---|
| 889 | SELECT
|
|---|
| 890 | n.name,
|
|---|
| 891 | (random() < 0.85) AS is_active,
|
|---|
| 892 | t.type,
|
|---|
| 893 |
|
|---|
| 894 | CASE t.type
|
|---|
| 895 | WHEN 'mammal' THEN mb.breed_name
|
|---|
| 896 | WHEN 'bird' THEN bb.breed_name
|
|---|
| 897 | WHEN 'fish' THEN fb.breed_name
|
|---|
| 898 | WHEN 'reptile' THEN rb.breed_name
|
|---|
| 899 | WHEN 'amphibian' THEN ab.breed_name
|
|---|
| 900 | END AS breed,
|
|---|
| 901 |
|
|---|
| 902 | CASE t.type
|
|---|
| 903 | WHEN 'mammal' THEN floor(random() * 240)::int
|
|---|
| 904 | WHEN 'bird' THEN floor(random() * 720)::int
|
|---|
| 905 | WHEN 'reptile' THEN floor(random() * 600)::int
|
|---|
| 906 | WHEN 'fish' THEN floor(random() * 240)::int
|
|---|
| 907 | WHEN 'amphibian' THEN floor(random() * 360)::int
|
|---|
| 908 | END AS age,
|
|---|
| 909 |
|
|---|
| 910 | h.history,
|
|---|
| 911 | oa.owner_id
|
|---|
| 912 |
|
|---|
| 913 | FROM typed t
|
|---|
| 914 | CROSS JOIN breed_counts bc
|
|---|
| 915 | JOIN owner_assignment oa ON oa.pet_rn = t.rn
|
|---|
| 916 | JOIN owner_counts oc ON true
|
|---|
| 917 |
|
|---|
| 918 | JOIN names n
|
|---|
| 919 | ON n.rn = ((abs(hashtext(t.rn::text || 'pet_name_' || t.rn)) % bc.names_cnt) + 1)
|
|---|
| 920 |
|
|---|
| 921 | JOIN history h
|
|---|
| 922 | ON h.rn = ((abs(hashtext(t.rn::text || 'pet_history_' || t.rn)) % bc.history_cnt) + 1)
|
|---|
| 923 |
|
|---|
| 924 | LEFT JOIN mammal_breeds mb
|
|---|
| 925 | ON t.type = 'mammal'
|
|---|
| 926 | AND mb.rn = ((abs(hashtext(t.rn::text || 'mammal_' || t.rn)) % bc.mammal_cnt) + 1)
|
|---|
| 927 |
|
|---|
| 928 | LEFT JOIN bird_breeds bb
|
|---|
| 929 | ON t.type = 'bird'
|
|---|
| 930 | AND bb.rn = ((abs(hashtext(t.rn::text || 'bird_' || t.rn)) % bc.bird_cnt) + 1)
|
|---|
| 931 |
|
|---|
| 932 | LEFT JOIN fish_breeds fb
|
|---|
| 933 | ON t.type = 'fish'
|
|---|
| 934 | AND fb.rn = ((abs(hashtext(t.rn::text || 'fish_' || t.rn)) % bc.fish_cnt) + 1)
|
|---|
| 935 |
|
|---|
| 936 | LEFT JOIN reptile_breeds rb
|
|---|
| 937 | ON t.type = 'reptile'
|
|---|
| 938 | AND rb.rn = ((abs(hashtext(t.rn::text || 'reptile_' || t.rn)) % bc.reptile_cnt) + 1)
|
|---|
| 939 |
|
|---|
| 940 | LEFT JOIN amphibian_breeds ab
|
|---|
| 941 | ON t.type = 'amphibian'
|
|---|
| 942 | AND ab.rn = ((abs(hashtext(t.rn::text || 'amphibian_' || t.rn)) % bc.amphibian_cnt) + 1);
|
|---|
| 943 |
|
|---|
| 944 | -- fix for small mistakes with csv
|
|---|
| 945 |
|
|---|
| 946 | UPDATE pet
|
|---|
| 947 | SET medical_history = 'Dental exam completed'
|
|---|
| 948 | WHERE id = 12;
|
|---|
| 949 |
|
|---|
| 950 | UPDATE pet
|
|---|
| 951 | SET medical_history = 'Eye exam completed'
|
|---|
| 952 | WHERE id = 57;
|
|---|
| 953 |
|
|---|
| 954 |
|
|---|
| 955 | -- ============================================================
|
|---|
| 956 | -- certificate
|
|---|
| 957 | -- ============================================================
|
|---|
| 958 |
|
|---|
| 959 | ALTER TABLE certificate
|
|---|
| 960 | ADD column category VARCHAR(50);
|
|---|
| 961 |
|
|---|
| 962 |
|
|---|
| 963 | CREATE TABLE temp_certificate_names (
|
|---|
| 964 | id bigserial primary key,
|
|---|
| 965 | name text,
|
|---|
| 966 | category text
|
|---|
| 967 |
|
|---|
| 968 | );
|
|---|
| 969 |
|
|---|
| 970 | COPY temp_certificate_names (name,category)
|
|---|
| 971 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/vet_assistance_certificates.csv'
|
|---|
| 972 | DELIMITER ',' CSV HEADER;
|
|---|
| 973 |
|
|---|
| 974 | INSERT INTO certificate (certificate_name, category, employee_id)
|
|---|
| 975 | SELECT
|
|---|
| 976 | t.name,
|
|---|
| 977 | t.category,
|
|---|
| 978 | e.id
|
|---|
| 979 | FROM
|
|---|
| 980 | (SELECT name, category, row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 981 | FROM temp_certificate_names) t,
|
|---|
| 982 | (SELECT id, row_number() OVER (ORDER BY random()) AS rn,
|
|---|
| 983 | count(*) OVER () AS total
|
|---|
| 984 | FROM employee
|
|---|
| 985 | WHERE role_id = 3) e
|
|---|
| 986 | WHERE e.rn = (t.rn % (SELECT count(*) FROM employee WHERE role_id = 3)) + 1;
|
|---|
| 987 |
|
|---|
| 988 | -- ============================================================
|
|---|
| 989 | -- specialization
|
|---|
| 990 | -- ============================================================
|
|---|
| 991 |
|
|---|
| 992 | CREATE TABLE temp_spec_data (
|
|---|
| 993 | id bigserial primary key,
|
|---|
| 994 | name text,
|
|---|
| 995 | number text
|
|---|
| 996 |
|
|---|
| 997 | );
|
|---|
| 998 |
|
|---|
| 999 | COPY temp_spec_data (name,number)
|
|---|
| 1000 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/vet_specializations.csv'
|
|---|
| 1001 | DELIMITER ',' CSV HEADER;
|
|---|
| 1002 |
|
|---|
| 1003 | -- Step 1: Assign Diplomate specializations to all role_id=2 employees
|
|---|
| 1004 | INSERT INTO specialization (specialization, license_number, employee_id)
|
|---|
| 1005 | SELECT
|
|---|
| 1006 | t.name,
|
|---|
| 1007 | t.number,
|
|---|
| 1008 | e.id
|
|---|
| 1009 | FROM
|
|---|
| 1010 | (SELECT name, number, row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 1011 | FROM temp_spec_data
|
|---|
| 1012 | WHERE name ILIKE '%diplomate%') t,
|
|---|
| 1013 | (SELECT id, row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 1014 | FROM employee
|
|---|
| 1015 | WHERE role_id = 2) e
|
|---|
| 1016 | WHERE e.rn = (t.rn % (SELECT count(*) FROM employee WHERE role_id = 2)) + 1;
|
|---|
| 1017 |
|
|---|
| 1018 |
|
|---|
| 1019 | INSERT INTO specialization (specialization, license_number, employee_id)
|
|---|
| 1020 | SELECT
|
|---|
| 1021 | t.name,
|
|---|
| 1022 | t.number,
|
|---|
| 1023 | e.id
|
|---|
| 1024 | FROM
|
|---|
| 1025 | (SELECT name, number, row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 1026 | FROM temp_spec_data
|
|---|
| 1027 | WHERE name ILIKE '%master%') t,
|
|---|
| 1028 | (SELECT id, row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 1029 | FROM employee
|
|---|
| 1030 | WHERE role_id = 2
|
|---|
| 1031 | AND id IN (SELECT employee_id FROM specialization WHERE specialization ILIKE '%diplomate%')
|
|---|
| 1032 | LIMIT (SELECT count(*)/2 FROM employee WHERE role_id = 2)
|
|---|
| 1033 | ) e
|
|---|
| 1034 | WHERE e.rn = (t.rn % (SELECT GREATEST(count(*)/2, 1) FROM employee WHERE role_id = 2)) + 1;
|
|---|
| 1035 |
|
|---|
| 1036 |
|
|---|
| 1037 | -- ============================================================
|
|---|
| 1038 | -- coupon
|
|---|
| 1039 | -- ============================================================
|
|---|
| 1040 |
|
|---|
| 1041 | INSERT INTO coupon (
|
|---|
| 1042 | code,
|
|---|
| 1043 | type,
|
|---|
| 1044 | value,
|
|---|
| 1045 | valid_from,
|
|---|
| 1046 | valid_to,
|
|---|
| 1047 | usage_limit,
|
|---|
| 1048 | usage_count,
|
|---|
| 1049 | is_active,
|
|---|
| 1050 | min_total
|
|---|
| 1051 | )
|
|---|
| 1052 | SELECT
|
|---|
| 1053 | chr(65 + (gs % 26)) ||
|
|---|
| 1054 | chr(65 + ((gs / 26) % 26)) ||
|
|---|
| 1055 | chr(65 + ((gs / 676) % 26)) ||
|
|---|
| 1056 | '-' || lpad((gs % 1000)::text, 3, '0') AS code,
|
|---|
| 1057 |
|
|---|
| 1058 | CASE
|
|---|
| 1059 | WHEN random() < 0.5 THEN 'fixed'
|
|---|
| 1060 | ELSE 'percentage'
|
|---|
| 1061 | END AS type,
|
|---|
| 1062 |
|
|---|
| 1063 | CASE
|
|---|
| 1064 | WHEN random() < 0.5
|
|---|
| 1065 | THEN round((random() * 50 + 5)::numeric, 2)
|
|---|
| 1066 | ELSE round((random() * 80 + 1)::numeric, 2)
|
|---|
| 1067 | END AS value,
|
|---|
| 1068 |
|
|---|
| 1069 | CURRENT_DATE - (random() * 30)::int,
|
|---|
| 1070 | CURRENT_DATE + (random() * 60)::int,
|
|---|
| 1071 |
|
|---|
| 1072 | u.usage_limit,
|
|---|
| 1073 | (random() * u.usage_limit)::int AS usage_count,
|
|---|
| 1074 |
|
|---|
| 1075 | (random() < 0.8),
|
|---|
| 1076 | round((random() * 200)::numeric, 2)
|
|---|
| 1077 |
|
|---|
| 1078 | FROM generate_series(1, 1000) gs
|
|---|
| 1079 | CROSS JOIN LATERAL (
|
|---|
| 1080 | SELECT (random() * 90 + 10)::int AS usage_limit
|
|---|
| 1081 | ) u;
|
|---|
| 1082 |
|
|---|
| 1083 |
|
|---|
| 1084 | -- ============================================================
|
|---|
| 1085 | -- prescription
|
|---|
| 1086 | -- ============================================================
|
|---|
| 1087 |
|
|---|
| 1088 | CREATE TABLE temp_prescription_advice(
|
|---|
| 1089 | id bigserial primary key,
|
|---|
| 1090 | advice text
|
|---|
| 1091 | );
|
|---|
| 1092 |
|
|---|
| 1093 | COPY temp_prescription_advice (advice)
|
|---|
| 1094 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/pet_prescriptions_advice.csv'
|
|---|
| 1095 | DELIMITER ',' CSV HEADER;
|
|---|
| 1096 |
|
|---|
| 1097 |
|
|---|
| 1098 | -- ============================================================
|
|---|
| 1099 | -- examination_room
|
|---|
| 1100 | -- ============================================================
|
|---|
| 1101 |
|
|---|
| 1102 | INSERT INTO examination_room (room_number, type, capacity, status)
|
|---|
| 1103 | SELECT
|
|---|
| 1104 | gs::text AS room_number,
|
|---|
| 1105 | CASE
|
|---|
| 1106 | WHEN r < 0.55 THEN 'examination'
|
|---|
| 1107 | WHEN r < 0.75 THEN 'surgery'
|
|---|
| 1108 | WHEN r < 0.90 THEN 'patient ward'
|
|---|
| 1109 | WHEN r < 0.95 THEN 'radiology'
|
|---|
| 1110 | ELSE 'laboratory'
|
|---|
| 1111 | END AS type,
|
|---|
| 1112 |
|
|---|
| 1113 | CASE
|
|---|
| 1114 | WHEN r < 0.55 THEN 1
|
|---|
| 1115 | WHEN r < 0.75 THEN 1
|
|---|
| 1116 | WHEN r < 0.90 THEN 10 + (random() * 10)::int
|
|---|
| 1117 | WHEN r < 0.95 THEN 2 + (random() * 3)::int
|
|---|
| 1118 | ELSE 2 + (random() * 4)::int
|
|---|
| 1119 | END AS capacity,
|
|---|
| 1120 |
|
|---|
| 1121 | 'available' AS status
|
|---|
| 1122 | FROM (
|
|---|
| 1123 | SELECT gs, random() AS r
|
|---|
| 1124 | FROM generate_series(1, 15) gs
|
|---|
| 1125 | ) x;
|
|---|
| 1126 |
|
|---|
| 1127 |
|
|---|
| 1128 | -- ============================================================
|
|---|
| 1129 | -- medicine & shop_item
|
|---|
| 1130 | -- ============================================================
|
|---|
| 1131 | -- 1. shop_item_category → add 'Medicine' category
|
|---|
| 1132 | -- 2. shop_item → ~60 medicines available in the shop
|
|---|
| 1133 | -- 3. medicine → ~120 total: ~60 linked to shop, ~60 prescription-only
|
|---|
| 1134 | -- 4. prescription → one per qualifying examination
|
|---|
| 1135 | -- 5. prescription_medicine → M:N join with dosage/num_days
|
|---|
| 1136 | -- ============================================================
|
|---|
| 1137 |
|
|---|
| 1138 | -- ============================================================
|
|---|
| 1139 | -- shop_item_category
|
|---|
| 1140 | -- ============================================================
|
|---|
| 1141 |
|
|---|
| 1142 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1143 | VALUES ('Pet Supplies', NULL)
|
|---|
| 1144 | ON CONFLICT DO NOTHING;
|
|---|
| 1145 |
|
|---|
| 1146 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1147 | SELECT 'Medicine', id
|
|---|
| 1148 | FROM shop_item_category
|
|---|
| 1149 | WHERE name = 'Pet Supplies'
|
|---|
| 1150 | ON CONFLICT DO NOTHING;
|
|---|
| 1151 |
|
|---|
| 1152 |
|
|---|
| 1153 | -- ============================================================
|
|---|
| 1154 | -- shop_item - medicines sold in shop (~60 items)
|
|---|
| 1155 | -- shop_item_category_id pointing to 'Medicine' category
|
|---|
| 1156 | -- ============================================================
|
|---|
| 1157 |
|
|---|
| 1158 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1159 | SELECT
|
|---|
| 1160 | med_name,
|
|---|
| 1161 | round((3.50 + random() * 96.50)::numeric, 2) AS price,
|
|---|
| 1162 | (floor(random() * 150) + 5)::int AS stock,
|
|---|
| 1163 | (SELECT id FROM shop_item_category WHERE name = 'Medicine') AS shop_item_category_id
|
|---|
| 1164 | FROM (VALUES
|
|---|
| 1165 | ('Amoxicillin 250mg Tablets'),
|
|---|
| 1166 | ('Amoxicillin 500mg Capsules'),
|
|---|
| 1167 | ('Metronidazole 200mg Tablets'),
|
|---|
| 1168 | ('Metronidazole 400mg Tablets'),
|
|---|
| 1169 | ('Doxycycline 100mg Capsules'),
|
|---|
| 1170 | ('Enrofloxacin 50mg Tablets'),
|
|---|
| 1171 | ('Enrofloxacin 150mg Tablets'),
|
|---|
| 1172 | ('Trimethoprim-Sulfa 480mg Tablets'),
|
|---|
| 1173 | ('Cephalexin 250mg Capsules'),
|
|---|
| 1174 | ('Cephalexin 500mg Capsules'),
|
|---|
| 1175 | ('Prednisolone 5mg Tablets'),
|
|---|
| 1176 | ('Prednisolone 20mg Tablets'),
|
|---|
| 1177 | ('Dexamethasone 0.5mg Tablets'),
|
|---|
| 1178 | ('Methylprednisolone 4mg Tablets'),
|
|---|
| 1179 | ('Hydrocortisone 10mg Tablets'),
|
|---|
| 1180 | ('Furosemide 40mg Tablets'),
|
|---|
| 1181 | ('Spironolactone 25mg Tablets'),
|
|---|
| 1182 | ('Enalapril 5mg Tablets'),
|
|---|
| 1183 | ('Atenolol 25mg Tablets'),
|
|---|
| 1184 | ('Digoxin 0.125mg Tablets'),
|
|---|
| 1185 | ('Carprofen 50mg Chewable Tablets'),
|
|---|
| 1186 | ('Meloxicam 1mg Tablets'),
|
|---|
| 1187 | ('Meloxicam Oral Suspension 1.5mg/ml'),
|
|---|
| 1188 | ('Tramadol 50mg Tablets'),
|
|---|
| 1189 | ('Gabapentin 100mg Capsules'),
|
|---|
| 1190 | ('Gabapentin 300mg Capsules'),
|
|---|
| 1191 | ('Phenobarbital 30mg Tablets'),
|
|---|
| 1192 | ('Potassium Bromide 325mg Capsules'),
|
|---|
| 1193 | ('Levetiracetam 250mg Tablets'),
|
|---|
| 1194 | ('Omeprazole 20mg Capsules'),
|
|---|
| 1195 | ('Famotidine 20mg Tablets'),
|
|---|
| 1196 | ('Metoclopramide 10mg Tablets'),
|
|---|
| 1197 | ('Ondansetron 4mg Tablets'),
|
|---|
| 1198 | ('Maropitant 16mg Tablets'),
|
|---|
| 1199 | ('Sucralfate 1g Tablets'),
|
|---|
| 1200 | ('Lactulose Oral Solution 667mg/ml'),
|
|---|
| 1201 | ('Loperamide 2mg Capsules'),
|
|---|
| 1202 | ('Tylosin 250mg Powder'),
|
|---|
| 1203 | ('Clindamycin 75mg Capsules'),
|
|---|
| 1204 | ('Clindamycin 150mg Capsules'),
|
|---|
| 1205 | ('Ketoconazole 200mg Tablets'),
|
|---|
| 1206 | ('Fluconazole 50mg Capsules'),
|
|---|
| 1207 | ('Itraconazole 100mg Capsules'),
|
|---|
| 1208 | ('Fenbendazole 150mg Granules'),
|
|---|
| 1209 | ('Pyrantel Pamoate Oral Suspension'),
|
|---|
| 1210 | ('Ivermectin 1% Oral Solution'),
|
|---|
| 1211 | ('Milbemycin Oxime 2.3mg Tablets'),
|
|---|
| 1212 | ('Praziquantel 50mg Tablets'),
|
|---|
| 1213 | ('Doxycycline Hyclate 100mg Tablets'),
|
|---|
| 1214 | ('Chloramphenicol 250mg Capsules'),
|
|---|
| 1215 | ('Cyclosporine 25mg Capsules'),
|
|---|
| 1216 | ('Cyclosporine 100mg Capsules'),
|
|---|
| 1217 | ('Apoquel 3.6mg Tablets'),
|
|---|
| 1218 | ('Apoquel 16mg Tablets'),
|
|---|
| 1219 | ('Hydroxyzine 25mg Tablets'),
|
|---|
| 1220 | ('Diphenhydramine 25mg Capsules'),
|
|---|
| 1221 | ('Vitamin B12 Injection 1000mcg/ml'),
|
|---|
| 1222 | ('Iron Dextran 100mg/ml Injection'),
|
|---|
| 1223 | ('Calcium Gluconate 10% Injection'),
|
|---|
| 1224 | ('Saline 0.9% Flush Solution 10ml')
|
|---|
| 1225 | ) AS t(med_name);
|
|---|
| 1226 |
|
|---|
| 1227 |
|
|---|
| 1228 | -- ============================================================
|
|---|
| 1229 | -- medicine table
|
|---|
| 1230 | -- ~60 medicines that exist in the shop (linked via shop_item_id fk)
|
|---|
| 1231 | -- ~60 medicines that are prescription-only (shop_item_id IS NULL)
|
|---|
| 1232 | -- ============================================================
|
|---|
| 1233 |
|
|---|
| 1234 | -- a. medicines that are in the shop - match by name to shop_item
|
|---|
| 1235 | INSERT INTO medicine (name, manufacturer, description, shop_item_id)
|
|---|
| 1236 | SELECT
|
|---|
| 1237 | si.name,
|
|---|
| 1238 | mfr,
|
|---|
| 1239 | descr,
|
|---|
| 1240 | si.id AS shop_item_id
|
|---|
| 1241 | FROM shop_item si
|
|---|
| 1242 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id
|
|---|
| 1243 | JOIN (VALUES
|
|---|
| 1244 | ('Amoxicillin 250mg Tablets', 'Zoetis Inc.', 'Broad-spectrum penicillin antibiotic for bacterial infections'),
|
|---|
| 1245 | ('Amoxicillin 500mg Capsules', 'Zoetis Inc.', 'Higher-dose penicillin for severe or systemic bacterial infections'),
|
|---|
| 1246 | ('Metronidazole 200mg Tablets', 'Norbrook Laboratories', 'Antibiotic and antiprotozoal for GI and anaerobic infections'),
|
|---|
| 1247 | ('Metronidazole 400mg Tablets', 'Norbrook Laboratories', 'Higher-dose metronidazole for systemic anaerobic infections'),
|
|---|
| 1248 | ('Doxycycline 100mg Capsules', 'Boehringer Ingelheim', 'Tetracycline antibiotic effective against intracellular pathogens'),
|
|---|
| 1249 | ('Enrofloxacin 50mg Tablets', 'Bayer Animal Health', 'Fluoroquinolone antibiotic for urinary and soft tissue infections'),
|
|---|
| 1250 | ('Enrofloxacin 150mg Tablets', 'Bayer Animal Health', 'Higher-dose fluoroquinolone for large breeds or severe infections'),
|
|---|
| 1251 | ('Trimethoprim-Sulfa 480mg Tablets', 'Vetoquinol', 'Combination sulfonamide for respiratory and urinary tract infections'),
|
|---|
| 1252 | ('Cephalexin 250mg Capsules', 'Dechra Veterinary', 'First-generation cephalosporin for skin and soft tissue infections'),
|
|---|
| 1253 | ('Cephalexin 500mg Capsules', 'Dechra Veterinary', 'Higher-dose cephalosporin for pyoderma and wound infections'),
|
|---|
| 1254 | ('Prednisolone 5mg Tablets', 'Virbac Animal Health', 'Corticosteroid for inflammatory and autoimmune conditions'),
|
|---|
| 1255 | ('Prednisolone 20mg Tablets', 'Virbac Animal Health', 'Higher-dose corticosteroid for severe allergic or inflammatory disease'),
|
|---|
| 1256 | ('Dexamethasone 0.5mg Tablets', 'Elanco Animal Health', 'Potent corticosteroid for acute inflammatory reactions'),
|
|---|
| 1257 | ('Methylprednisolone 4mg Tablets', 'Pfizer Animal Health', 'Intermediate corticosteroid for chronic inflammatory conditions'),
|
|---|
| 1258 | ('Hydrocortisone 10mg Tablets', 'Norbrook Laboratories', 'Mild corticosteroid for adrenal insufficiency and mild inflammation'),
|
|---|
| 1259 | ('Furosemide 40mg Tablets', 'Boehringer Ingelheim', 'Loop diuretic for congestive heart failure and oedema'),
|
|---|
| 1260 | ('Spironolactone 25mg Tablets', 'Dechra Veterinary', 'Potassium-sparing diuretic for cardiac and hepatic disease'),
|
|---|
| 1261 | ('Enalapril 5mg Tablets', 'Zoetis Inc.', 'ACE inhibitor for hypertension and congestive heart failure'),
|
|---|
| 1262 | ('Atenolol 25mg Tablets', 'Elanco Animal Health', 'Beta-blocker for hypertrophic cardiomyopathy and arrhythmias'),
|
|---|
| 1263 | ('Digoxin 0.125mg Tablets', 'Pfizer Animal Health', 'Cardiac glycoside for atrial fibrillation and heart failure'),
|
|---|
| 1264 | ('Carprofen 50mg Chewable Tablets', 'Zoetis Inc.', 'NSAID for pain and inflammation in musculoskeletal disease'),
|
|---|
| 1265 | ('Meloxicam 1mg Tablets', 'Boehringer Ingelheim', 'NSAID for osteoarthritis pain and post-operative analgesia'),
|
|---|
| 1266 | ('Meloxicam Oral Suspension 1.5mg/ml','Boehringer Ingelheim', 'Liquid NSAID formulation for cats and small dogs'),
|
|---|
| 1267 | ('Tramadol 50mg Tablets', 'Norbrook Laboratories', 'Opioid analgesic for moderate to severe pain management'),
|
|---|
| 1268 | ('Gabapentin 100mg Capsules', 'Dechra Veterinary', 'Anticonvulsant and analgesic for neuropathic pain'),
|
|---|
| 1269 | ('Gabapentin 300mg Capsules', 'Dechra Veterinary', 'Higher-dose gabapentin for chronic pain or seizure management'),
|
|---|
| 1270 | ('Phenobarbital 30mg Tablets', 'Virbac Animal Health', 'Barbiturate anticonvulsant for idiopathic epilepsy'),
|
|---|
| 1271 | ('Potassium Bromide 325mg Capsules', 'Vetoquinol', 'Adjunctive anticonvulsant for refractory epilepsy'),
|
|---|
| 1272 | ('Levetiracetam 250mg Tablets', 'Bayer Animal Health', 'Novel anticonvulsant with favourable safety profile'),
|
|---|
| 1273 | ('Omeprazole 20mg Capsules', 'Elanco Animal Health', 'Proton pump inhibitor for gastric ulcer and acid reflux'),
|
|---|
| 1274 | ('Famotidine 20mg Tablets', 'Pfizer Animal Health', 'H2 blocker for gastric hyperacidity and stress ulceration'),
|
|---|
| 1275 | ('Metoclopramide 10mg Tablets', 'Zoetis Inc.', 'Prokinetic antiemetic for gastric motility disorders'),
|
|---|
| 1276 | ('Ondansetron 4mg Tablets', 'Norbrook Laboratories', 'Serotonin antagonist antiemetic for chemotherapy-induced nausea'),
|
|---|
| 1277 | ('Maropitant 16mg Tablets', 'Zoetis Inc.', 'NK1 receptor antagonist antiemetic for motion sickness and vomiting'),
|
|---|
| 1278 | ('Sucralfate 1g Tablets', 'Dechra Veterinary', 'Mucosal protectant for gastric and duodenal ulcers'),
|
|---|
| 1279 | ('Lactulose Oral Solution 667mg/ml', 'Virbac Animal Health', 'Osmotic laxative for hepatic encephalopathy and constipation'),
|
|---|
| 1280 | ('Loperamide 2mg Capsules', 'Elanco Animal Health', 'Opioid receptor agonist for acute non-specific diarrhoea'),
|
|---|
| 1281 | ('Tylosin 250mg Powder', 'Elanco Animal Health', 'Macrolide antibiotic for chronic enteropathy and diarrhoea'),
|
|---|
| 1282 | ('Clindamycin 75mg Capsules', 'Zoetis Inc.', 'Lincosamide antibiotic for anaerobic and dental infections'),
|
|---|
| 1283 | ('Clindamycin 150mg Capsules', 'Zoetis Inc.', 'Higher-dose clindamycin for deep tissue and bone infections'),
|
|---|
| 1284 | ('Ketoconazole 200mg Tablets', 'Dechra Veterinary', 'Azole antifungal for dermatophytosis and systemic mycoses'),
|
|---|
| 1285 | ('Fluconazole 50mg Capsules', 'Pfizer Animal Health', 'Triazole antifungal for Candida and cryptococcal infections'),
|
|---|
| 1286 | ('Itraconazole 100mg Capsules', 'Boehringer Ingelheim', 'Broad-spectrum antifungal for Aspergillus and dermatophytes'),
|
|---|
| 1287 | ('Fenbendazole 150mg Granules', 'Intervet-Schering Plough', 'Benzimidazole anthelmintic for roundworms, hookworms and Giardia'),
|
|---|
| 1288 | ('Pyrantel Pamoate Oral Suspension', 'Elanco Animal Health', 'Anthelmintic for roundworm and hookworm infections'),
|
|---|
| 1289 | ('Ivermectin 1% Oral Solution', 'Merial', 'Macrocyclic lactone for mites, lice and internal parasites'),
|
|---|
| 1290 | ('Milbemycin Oxime 2.3mg Tablets', 'Novartis Animal Health', 'Heartworm prevention and intestinal parasite control'),
|
|---|
| 1291 | ('Praziquantel 50mg Tablets', 'Bayer Animal Health', 'Cestocidal agent for tapeworm infections'),
|
|---|
| 1292 | ('Doxycycline Hyclate 100mg Tablets', 'Boehringer Ingelheim', 'Hyclate salt form with improved bioavailability for systemic infections'),
|
|---|
| 1293 | ('Chloramphenicol 250mg Capsules', 'Vetoquinol', 'Broad-spectrum antibiotic reserved for resistant infections'),
|
|---|
| 1294 | ('Cyclosporine 25mg Capsules', 'Elanco Animal Health', 'Immunosuppressant for immune-mediated skin and eye disease'),
|
|---|
| 1295 | ('Cyclosporine 100mg Capsules', 'Elanco Animal Health', 'Higher-dose cyclosporine for large breed immune-mediated disease'),
|
|---|
| 1296 | ('Apoquel 3.6mg Tablets', 'Zoetis Inc.', 'JAK inhibitor for pruritus and allergic dermatitis in dogs'),
|
|---|
| 1297 | ('Apoquel 16mg Tablets', 'Zoetis Inc.', 'Higher-dose Apoquel for larger dogs with atopic dermatitis'),
|
|---|
| 1298 | ('Hydroxyzine 25mg Tablets', 'Dechra Veterinary', 'Antihistamine for pruritic skin disease and anxiety'),
|
|---|
| 1299 | ('Diphenhydramine 25mg Capsules', 'Norbrook Laboratories', 'First-generation antihistamine for allergic reactions'),
|
|---|
| 1300 | ('Vitamin B12 Injection 1000mcg/ml', 'Vetoquinol', 'Cyanocobalamin supplement for malabsorption and neuropathy'),
|
|---|
| 1301 | ('Iron Dextran 100mg/ml Injection', 'Virbac Animal Health', 'Parenteral iron supplement for iron-deficiency anaemia in neonates'),
|
|---|
| 1302 | ('Calcium Gluconate 10% Injection', 'Pfizer Animal Health', 'IV calcium supplementation for hypocalcaemia and eclampsia'),
|
|---|
| 1303 | ('Saline 0.9% Flush Solution 10ml', 'Zoetis Inc.', 'Sterile saline for catheter flushing and wound irrigation')
|
|---|
| 1304 | ) AS m(med_name, mfr, descr) ON si.name = m.med_name
|
|---|
| 1305 | WHERE sic.name = 'Medicine';
|
|---|
| 1306 |
|
|---|
| 1307 |
|
|---|
| 1308 | -- b. prescription-only medicines (no shop_item)
|
|---|
| 1309 | INSERT INTO medicine (name, manufacturer, description, shop_item_id)
|
|---|
| 1310 | VALUES
|
|---|
| 1311 | ('Amikacin 250mg/ml Injection', 'Norbrook Laboratories', 'Aminoglycoside antibiotic for gram-negative infections resistant to other antibiotics', NULL),
|
|---|
| 1312 | ('Gentamicin 40mg/ml Injection', 'Dechra Veterinary', 'Aminoglycoside for serious gram-negative infections; requires renal monitoring', NULL),
|
|---|
| 1313 | ('Imipenem-Cilastatin 500mg Injection', 'Pfizer Animal Health', 'Carbapenem for multidrug-resistant bacterial infections', NULL),
|
|---|
| 1314 | ('Cefovecin 80mg/ml Injection', 'Zoetis Inc.', 'Long-acting cephalosporin injection; single dose covers 14 days', NULL),
|
|---|
| 1315 | ('Marbofloxacin 50mg Tablets', 'Vetoquinol', 'Third-generation fluoroquinolone for skin and urinary infections', NULL),
|
|---|
| 1316 | ('Pradofloxacin 15mg Tablets', 'Bayer Animal Health', 'Broad-spectrum fluoroquinolone including anaerobes; cats only', NULL),
|
|---|
| 1317 | ('Azithromycin 250mg Capsules', 'Boehringer Ingelheim', 'Macrolide antibiotic for respiratory and intracellular infections', NULL),
|
|---|
| 1318 | ('Rifampicin 150mg Capsules', 'Virbac Animal Health', 'Reserved for Rhodococcus equi and methicillin-resistant staphylococci', NULL),
|
|---|
| 1319 | ('Linezolid 600mg Tablets', 'Pfizer Animal Health', 'Oxazolidinone for vancomycin-resistant enterococci', NULL),
|
|---|
| 1320 | ('Vancomycin 500mg Injection', 'Elanco Animal Health', 'Glycopeptide antibiotic; last-resort therapy for MRSA', NULL),
|
|---|
| 1321 | ('Hydrocortisone Sodium Succinate Inj.', 'Zoetis Inc.', 'IV corticosteroid for anaphylaxis and Addisonian crisis', NULL),
|
|---|
| 1322 | ('Betamethasone 4mg/ml Injection', 'Norbrook Laboratories', 'Potent long-acting corticosteroid for inflammatory conditions', NULL),
|
|---|
| 1323 | ('Triamcinolone 10mg/ml Injection', 'Dechra Veterinary', 'Intermediate-acting corticosteroid for intra-articular use', NULL),
|
|---|
| 1324 | ('Terbinafine 250mg Tablets', 'Elanco Animal Health', 'Allylamine antifungal for dermatophyte infections', NULL),
|
|---|
| 1325 | ('Voriconazole 200mg Tablets', 'Pfizer Animal Health', 'Extended-spectrum triazole for Aspergillus and resistant Candida', NULL),
|
|---|
| 1326 | ('Amphotericin B 50mg Injection', 'Boehringer Ingelheim', 'Polyene antifungal for systemic mycoses; nephrotoxic', NULL),
|
|---|
| 1327 | ('Miltefosine 20mg Capsules', 'Virbac Animal Health', 'Antiprotozoal for feline leishmaniosis', NULL),
|
|---|
| 1328 | ('Ronidazole 100mg Tablets', 'Dechra Veterinary', 'Nitroimidazole for feline tritrichomoniasis', NULL),
|
|---|
| 1329 | ('Atovaquone 150mg Suspension', 'Norbrook Laboratories', 'Antiprotozoal for Babesia and Cytauxzoon infections', NULL),
|
|---|
| 1330 | ('Allopurinol 100mg Tablets', 'Elanco Animal Health', 'Xanthine oxidase inhibitor for urate urolithiasis in Dalmatians', NULL),
|
|---|
| 1331 | ('Pimobendan 1.25mg Tablets', 'Boehringer Ingelheim', 'Phosphodiesterase inhibitor and Ca-sensitiser for DCM and MVD', NULL),
|
|---|
| 1332 | ('Diltiazem 30mg Tablets', 'Dechra Veterinary', 'Calcium channel blocker for feline hypertrophic cardiomyopathy', NULL),
|
|---|
| 1333 | ('Amlodipine 1.25mg Tablets', 'Pfizer Animal Health', 'Calcium channel blocker for systemic hypertension in cats', NULL),
|
|---|
| 1334 | ('Benazepril 5mg Tablets', 'Vetoquinol', 'ACE inhibitor for chronic kidney disease and hypertension', NULL),
|
|---|
| 1335 | ('Telmisartan 4mg/ml Oral Solution', 'Boehringer Ingelheim', 'Angiotensin II receptor blocker for feline CKD proteinuria', NULL),
|
|---|
| 1336 | ('Sildenafil 25mg Tablets', 'Zoetis Inc.', 'PDE-5 inhibitor for pulmonary arterial hypertension', NULL),
|
|---|
| 1337 | ('Heparin 5000 IU/ml Injection', 'Virbac Animal Health', 'Anticoagulant for thromboembolism and DIC management', NULL),
|
|---|
| 1338 | ('Clopidogrel 75mg Tablets', 'Norbrook Laboratories', 'Antiplatelet for feline arterial thromboembolism prevention', NULL),
|
|---|
| 1339 | ('Pentoxifylline 400mg Tablets', 'Elanco Animal Health', 'Haemorheological agent for vasculitis and ischaemic disease', NULL),
|
|---|
| 1340 | ('Levothyroxine 0.1mg Tablets', 'Dechra Veterinary', 'Thyroid hormone replacement for canine hypothyroidism', NULL),
|
|---|
| 1341 | ('Methimazole 5mg Tablets', 'Virbac Animal Health', 'Thioamide for feline hyperthyroidism; inhibits thyroid synthesis', NULL),
|
|---|
| 1342 | ('Trilostane 30mg Capsules', 'Dechra Veterinary', '3beta-HSD inhibitor for hyperadrenocorticism (Cushing disease)', NULL),
|
|---|
| 1343 | ('Mitotane 500mg Tablets', 'Pfizer Animal Health', 'Adrenocorticolytic for pituitary-dependent hyperadrenocorticism', NULL),
|
|---|
| 1344 | ('Desoxycorticosterone 25mg/ml Inj.', 'Elanco Animal Health', 'Mineralocorticoid for canine hypoadrenocorticism (Addison disease)', NULL),
|
|---|
| 1345 | ('Cabergoline 0.05mg Tablets', 'Norbrook Laboratories', 'Dopamine agonist for false pregnancy and hyperprolactinaemia', NULL),
|
|---|
| 1346 | ('Misoprostol 200mcg Tablets', 'Boehringer Ingelheim', 'Prostaglandin E1 analogue for GI mucosal protection with NSAIDs', NULL),
|
|---|
| 1347 | ('Cisapride 5mg Tablets', 'Virbac Animal Health', 'Prokinetic for feline megacolon and gastric motility disorders', NULL),
|
|---|
| 1348 | ('Ursodiol 50mg Capsules', 'Dechra Veterinary', 'Bile acid for cholelithiasis and chronic hepatitis', NULL),
|
|---|
| 1349 | ('S-Adenosylmethionine 200mg Tablets', 'Zoetis Inc.', 'Hepatoprotectant for liver disease and oxidative stress', NULL),
|
|---|
| 1350 | ('Silymarin 35mg Capsules', 'Vetoquinol', 'Milk thistle extract hepatoprotectant for chronic hepatopathy', NULL),
|
|---|
| 1351 | ('Acetylcysteine 20% Solution', 'Elanco Animal Health', 'Mucolytic and antidote for paracetamol toxicosis in cats', NULL),
|
|---|
| 1352 | ('Atropine 0.6mg/ml Injection', 'Zoetis Inc.', 'Anticholinergic for bradycardia, organophosphate toxicosis, pre-anaesthesia', NULL),
|
|---|
| 1353 | ('Dopamine 40mg/ml Injection', 'Pfizer Animal Health', 'Catecholamine for cardiogenic shock and acute hypotension', NULL),
|
|---|
| 1354 | ('Dobutamine 12.5mg/ml Injection', 'Boehringer Ingelheim', 'Inotrope for decompensated heart failure and cardiogenic shock', NULL),
|
|---|
| 1355 | ('Norepinephrine 1mg/ml Injection', 'Norbrook Laboratories', 'Vasopressor for distributive shock unresponsive to fluids', NULL),
|
|---|
| 1356 | ('Mannitol 20% Infusion', 'Dechra Veterinary', 'Osmotic diuretic for cerebral oedema and acute glaucoma', NULL),
|
|---|
| 1357 | ('Hypertonic Saline 7.2% Infusion', 'Virbac Animal Health', 'Resuscitation fluid for haemorrhagic shock and head trauma', NULL),
|
|---|
| 1358 | ('Fresh Frozen Plasma (canine)', 'Animal Blood Resources', 'Coagulopathy treatment; provides clotting factors and albumin', NULL),
|
|---|
| 1359 | ('Hydroxyethyl Starch 6% Infusion', 'Elanco Animal Health', 'Colloid volume expander for hypoproteinaemia and shock', NULL),
|
|---|
| 1360 | ('Dextrose 50% Injection', 'Zoetis Inc.', 'Concentrated glucose for hypoglycaemia; dilute before IV use', NULL),
|
|---|
| 1361 | ('Potassium Chloride 15% Injection', 'Norbrook Laboratories', 'IV potassium supplementation; must be diluted; cardiac monitoring required', NULL),
|
|---|
| 1362 | ('Sodium Bicarbonate 8.4% Injection', 'Pfizer Animal Health', 'Alkalinising agent for severe metabolic acidosis', NULL),
|
|---|
| 1363 | ('Propofol 10mg/ml Injection', 'Zoetis Inc.', 'IV induction agent for general anaesthesia; rapid onset', NULL),
|
|---|
| 1364 | ('Alfaxalone 10mg/ml Injection', 'Jurox Animal Health', 'Neurosteroid anaesthetic for induction and TIVA in cats and dogs', NULL),
|
|---|
| 1365 | ('Ketamine 100mg/ml Injection', 'Dechra Veterinary', 'Dissociative anaesthetic; used in combination protocols', NULL),
|
|---|
| 1366 | ('Midazolam 5mg/ml Injection', 'Virbac Animal Health', 'Benzodiazepine for sedation, co-induction and status epilepticus', NULL),
|
|---|
| 1367 | ('Medetomidine 1mg/ml Injection', 'Orion Pharma', 'Alpha-2 agonist for sedation and pre-anaesthetic medication', NULL),
|
|---|
| 1368 | ('Buprenorphine 0.3mg/ml Injection', 'Norbrook Laboratories', 'Partial opioid agonist for perioperative and chronic pain', NULL),
|
|---|
| 1369 | ('Methadone 10mg/ml Injection', 'Dechra Veterinary', 'Full mu-opioid agonist for perioperative pain; used IV or IM', NULL),
|
|---|
| 1370 | ('Morphine 10mg/ml Injection', 'Elanco Animal Health', 'Classic opioid analgesic for severe acute pain; epidural use', NULL),
|
|---|
| 1371 | ('Fentanyl 0.05mg/ml Injection', 'Pfizer Animal Health', 'Short-acting opioid for intraoperative analgesia and CRI', NULL);
|
|---|
| 1372 |
|
|---|
| 1373 |
|
|---|
| 1374 | -- ============================================================
|
|---|
| 1375 | -- appointment
|
|---|
| 1376 | -- one appointment per owner-pet pair
|
|---|
| 1377 | -- phone copied from owner
|
|---|
| 1378 | -- ============================================================
|
|---|
| 1379 |
|
|---|
| 1380 | INSERT INTO appointment (date_appointment, reason, phone, owner_id, pet_id)
|
|---|
| 1381 | SELECT
|
|---|
| 1382 | CURRENT_DATE - (floor(random() * 730) + 1)::int AS date_appointment,
|
|---|
| 1383 | reason_list.reason,
|
|---|
| 1384 | o.phone,
|
|---|
| 1385 | o.id AS owner_id,
|
|---|
| 1386 | p.id AS pet_id
|
|---|
| 1387 | FROM owner o
|
|---|
| 1388 | JOIN LATERAL (
|
|---|
| 1389 | -- Pick one random pet belonging to this owner
|
|---|
| 1390 | SELECT id
|
|---|
| 1391 | FROM pet
|
|---|
| 1392 | WHERE owner_id = o.id
|
|---|
| 1393 | ORDER BY random()
|
|---|
| 1394 | LIMIT 1
|
|---|
| 1395 | ) p ON true
|
|---|
| 1396 | CROSS JOIN LATERAL (
|
|---|
| 1397 | SELECT reason
|
|---|
| 1398 | FROM (VALUES
|
|---|
| 1399 | ('Annual wellness check'),
|
|---|
| 1400 | ('Vaccination booster'),
|
|---|
| 1401 | ('Limping / lameness'),
|
|---|
| 1402 | ('Vomiting and lethargy'),
|
|---|
| 1403 | ('Skin rash and itching'),
|
|---|
| 1404 | ('Ear infection suspected'),
|
|---|
| 1405 | ('Eye discharge and redness'),
|
|---|
| 1406 | ('Dental check-up'),
|
|---|
| 1407 | ('Weight loss and poor appetite'),
|
|---|
| 1408 | ('Diarrhoea for more than 2 days'),
|
|---|
| 1409 | ('Post-operative follow-up'),
|
|---|
| 1410 | ('Suspected urinary tract infection'),
|
|---|
| 1411 | ('Respiratory difficulty'),
|
|---|
| 1412 | ('Wound assessment'),
|
|---|
| 1413 | ('Parasite prevention consultation'),
|
|---|
| 1414 | ('Behavioural changes'),
|
|---|
| 1415 | ('Mass / lump noticed'),
|
|---|
| 1416 | ('Allergic reaction'),
|
|---|
| 1417 | ('Pre-surgical blood work'),
|
|---|
| 1418 | ('General health concern')
|
|---|
| 1419 | ) AS r(reason)
|
|---|
| 1420 | WHERE o.id IS NOT NULL -- random per row
|
|---|
| 1421 | ORDER BY random()
|
|---|
| 1422 | LIMIT 1
|
|---|
| 1423 | ) reason_list;
|
|---|
| 1424 |
|
|---|
| 1425 | -- ============================================================
|
|---|
| 1426 | -- examination
|
|---|
| 1427 | -- one per appointment; date >= date_appointment
|
|---|
| 1428 | -- employee_id: random vet (role_id = 2)
|
|---|
| 1429 | -- examination_room_id: random room of type 'examination'
|
|---|
| 1430 | -- ============================================================
|
|---|
| 1431 |
|
|---|
| 1432 | INSERT INTO examination (date_examination, status, description, appointment_id, employee_id, examination_room_id)
|
|---|
| 1433 | SELECT
|
|---|
| 1434 | -- date is same day or up to 7 days after appointment
|
|---|
| 1435 | a.date_appointment + (floor(random() * 8))::int AS date_examination,
|
|---|
| 1436 |
|
|---|
| 1437 | -- most are completed; a few scheduled or cancelled
|
|---|
| 1438 | CASE
|
|---|
| 1439 | WHEN random() < 0.80 THEN 'completed'
|
|---|
| 1440 | WHEN random() < 0.90 THEN 'scheduled'
|
|---|
| 1441 | ELSE 'cancelled'
|
|---|
| 1442 | END AS status,
|
|---|
| 1443 |
|
|---|
| 1444 | desc_list.description,
|
|---|
| 1445 | a.id AS appointment_id,
|
|---|
| 1446 |
|
|---|
| 1447 | e.id AS employee_id,
|
|---|
| 1448 | r.id AS examination_room_id
|
|---|
| 1449 |
|
|---|
| 1450 | FROM appointment a
|
|---|
| 1451 | CROSS JOIN LATERAL (
|
|---|
| 1452 | SELECT description
|
|---|
| 1453 | FROM (VALUES
|
|---|
| 1454 | ('Patient presented for routine examination. Vitals within normal limits.'),
|
|---|
| 1455 | ('Initial assessment completed. Further diagnostics recommended.'),
|
|---|
| 1456 | ('Physical examination performed. Owner advised on treatment plan.'),
|
|---|
| 1457 | ('Patient examined; mild clinical signs noted. Medication prescribed.'),
|
|---|
| 1458 | ('Thorough examination carried out. No acute concerns identified.'),
|
|---|
| 1459 | ('Follow-up examination. Condition improving since last visit.'),
|
|---|
| 1460 | ('Examination completed. Lab samples collected for analysis.'),
|
|---|
| 1461 | ('Clinical signs assessed. Dietary modification recommended.'),
|
|---|
| 1462 | ('Patient stable. Monitoring plan established with owner.'),
|
|---|
| 1463 | ('Examination revealed localised inflammation. Treatment initiated.')
|
|---|
| 1464 | ) AS d(description)
|
|---|
| 1465 | WHERE a.id IS NOT NULL
|
|---|
| 1466 | ORDER BY random()
|
|---|
| 1467 | LIMIT 1
|
|---|
| 1468 | ) desc_list
|
|---|
| 1469 | -- random employee with role_id = 2
|
|---|
| 1470 | CROSS JOIN LATERAL (
|
|---|
| 1471 | SELECT id
|
|---|
| 1472 | FROM employee
|
|---|
| 1473 | WHERE role_id = 2
|
|---|
| 1474 | AND a.id IS NOT NULL
|
|---|
| 1475 | ORDER BY random()
|
|---|
| 1476 | LIMIT 1
|
|---|
| 1477 | ) e
|
|---|
| 1478 | -- random room with type = 'examination'
|
|---|
| 1479 | CROSS JOIN LATERAL (
|
|---|
| 1480 | SELECT id
|
|---|
| 1481 | FROM examination_room
|
|---|
| 1482 | WHERE type = 'examination'
|
|---|
| 1483 | AND a.id IS NOT NULL
|
|---|
| 1484 | ORDER BY random()
|
|---|
| 1485 | LIMIT 1
|
|---|
| 1486 | ) r;
|
|---|
| 1487 |
|
|---|
| 1488 | -- ============================================================
|
|---|
| 1489 | -- treatment_type
|
|---|
| 1490 | -- ============================================================
|
|---|
| 1491 |
|
|---|
| 1492 | INSERT INTO treatment_type (name) VALUES
|
|---|
| 1493 | ('prescription'),
|
|---|
| 1494 | ('vaccination'),
|
|---|
| 1495 | ('consultation'),
|
|---|
| 1496 | ('operation')
|
|---|
| 1497 | ON CONFLICT DO NOTHING;
|
|---|
| 1498 |
|
|---|
| 1499 | -- ============================================================
|
|---|
| 1500 | -- treatment (prescription type)
|
|---|
| 1501 | -- one treatment per completed examination
|
|---|
| 1502 | -- date_treatment >= date_examination
|
|---|
| 1503 | -- ============================================================
|
|---|
| 1504 |
|
|---|
| 1505 | INSERT INTO treatment (date_treatment, notes, treatment_type_id, examination_id)
|
|---|
| 1506 | SELECT
|
|---|
| 1507 | e.date_examination + (floor(random() * 4))::int AS date_treatment,
|
|---|
| 1508 |
|
|---|
| 1509 | notes_list.notes,
|
|---|
| 1510 |
|
|---|
| 1511 | (SELECT id FROM treatment_type WHERE name = 'prescription') AS treatment_type_id,
|
|---|
| 1512 |
|
|---|
| 1513 | e.id AS examination_id
|
|---|
| 1514 |
|
|---|
| 1515 | FROM examination e
|
|---|
| 1516 | CROSS JOIN LATERAL (
|
|---|
| 1517 | SELECT notes
|
|---|
| 1518 | FROM (VALUES
|
|---|
| 1519 | ('Prescription issued following clinical assessment.'),
|
|---|
| 1520 | ('Medication course prescribed; owner counselled on administration.'),
|
|---|
| 1521 | ('Short course of antibiotics prescribed pending culture results.'),
|
|---|
| 1522 | ('Anti-inflammatory therapy initiated; re-check in 10 days.'),
|
|---|
| 1523 | ('Antiparasitic treatment prescribed; environmental treatment advised.'),
|
|---|
| 1524 | ('Analgesic course prescribed for post-operative pain management.'),
|
|---|
| 1525 | ('Antifungal therapy prescribed; reassess in 3 weeks.'),
|
|---|
| 1526 | ('Prescription provided; monitor for adverse reactions.'),
|
|---|
| 1527 | ('Combination therapy prescribed; owner given written instructions.'),
|
|---|
| 1528 | ('Medication adjusted based on current clinical findings.')
|
|---|
| 1529 | ) AS n(notes)
|
|---|
| 1530 | WHERE e.id IS NOT NULL
|
|---|
| 1531 | ORDER BY random()
|
|---|
| 1532 | LIMIT 1
|
|---|
| 1533 | ) notes_list
|
|---|
| 1534 | WHERE e.status = 'completed';
|
|---|
| 1535 |
|
|---|
| 1536 | -- ============================================================
|
|---|
| 1537 | -- prescription
|
|---|
| 1538 | -- one prescription per examination that:
|
|---|
| 1539 | -- - has status = 'completed'
|
|---|
| 1540 | -- - has a treatment of type 'prescription'
|
|---|
| 1541 | -- ============================================================
|
|---|
| 1542 |
|
|---|
| 1543 | INSERT INTO prescription (examination_id, date_start, date_end, description)
|
|---|
| 1544 | SELECT
|
|---|
| 1545 | e.id AS examination_id,
|
|---|
| 1546 | e.date_examination AS date_start,
|
|---|
| 1547 | (e.date_examination + floor(random() * 21 + 7)::int)::date AS date_end,
|
|---|
| 1548 | pa.advice AS description
|
|---|
| 1549 | FROM examination e
|
|---|
| 1550 | JOIN treatment t ON t.examination_id = e.id
|
|---|
| 1551 | JOIN treatment_type tt ON tt.id = t.treatment_type_id
|
|---|
| 1552 | AND tt.name = 'prescription'
|
|---|
| 1553 | LEFT JOIN prescription p_existing
|
|---|
| 1554 | ON p_existing.examination_id = e.id
|
|---|
| 1555 | CROSS JOIN LATERAL (
|
|---|
| 1556 | SELECT advice
|
|---|
| 1557 | FROM temp_prescription_advice
|
|---|
| 1558 | WHERE e.id IS NOT NULL
|
|---|
| 1559 | ORDER BY random()
|
|---|
| 1560 | LIMIT 1
|
|---|
| 1561 | ) pa
|
|---|
| 1562 | WHERE e.status = 'completed'
|
|---|
| 1563 | AND p_existing.id IS NULL -- skip if already inserted
|
|---|
| 1564 | ON CONFLICT (examination_id) DO NOTHING;
|
|---|
| 1565 |
|
|---|
| 1566 |
|
|---|
| 1567 | -- ============================================================
|
|---|
| 1568 | -- prescription_medicine
|
|---|
| 1569 | -- Each prescription gets 1–4 medicines assigned.
|
|---|
| 1570 | -- ============================================================
|
|---|
| 1571 |
|
|---|
| 1572 | -- generate_series to produce 1–4 rows per prescription,
|
|---|
| 1573 | -- then deduplicate (medicine_id, prescription_id) pairs via DISTINCT ON.
|
|---|
| 1574 |
|
|---|
| 1575 | WITH prescription_slots AS (
|
|---|
| 1576 | SELECT
|
|---|
| 1577 | pr.id AS prescription_id,
|
|---|
| 1578 | gs.n AS slot,
|
|---|
| 1579 | floor(random() * 4 + 1)::int AS num_medicines -- how many this prescription actually wants
|
|---|
| 1580 | FROM prescription pr
|
|---|
| 1581 | CROSS JOIN generate_series(1, 4) AS gs(n)
|
|---|
| 1582 | ),
|
|---|
| 1583 |
|
|---|
| 1584 | wanted_slots AS (
|
|---|
| 1585 | SELECT prescription_id, slot
|
|---|
| 1586 | FROM prescription_slots
|
|---|
| 1587 | WHERE slot <= num_medicines
|
|---|
| 1588 | ),
|
|---|
| 1589 |
|
|---|
| 1590 | -- Assign a random medicine to each slot
|
|---|
| 1591 | med_counts AS (
|
|---|
| 1592 | SELECT count(*) AS total FROM medicine
|
|---|
| 1593 | ),
|
|---|
| 1594 |
|
|---|
| 1595 | assigned AS (
|
|---|
| 1596 | SELECT
|
|---|
| 1597 | ws.prescription_id,
|
|---|
| 1598 | ws.slot,
|
|---|
| 1599 | m.id AS medicine_id,
|
|---|
| 1600 | CASE
|
|---|
| 1601 | WHEN random() < 0.6 THEN 1 -- once daily
|
|---|
| 1602 | WHEN random() < 0.85 THEN 2 -- twice daily
|
|---|
| 1603 | ELSE 3 -- three times daily
|
|---|
| 1604 | END AS dosage,
|
|---|
| 1605 | (floor(random() * 21 + 3))::int AS num_days -- 3–23 days
|
|---|
| 1606 | FROM wanted_slots ws
|
|---|
| 1607 | CROSS JOIN med_counts mc
|
|---|
| 1608 | JOIN medicine m ON m.id = (
|
|---|
| 1609 | (abs(hashtext(ws.prescription_id::text || '-' || ws.slot::text)) % mc.total) + 1
|
|---|
| 1610 | )
|
|---|
| 1611 | ),
|
|---|
| 1612 |
|
|---|
| 1613 | -- deduplicate: if the same medicine appears twice in the same prescription, keep the first slot
|
|---|
| 1614 | deduped AS (
|
|---|
| 1615 | SELECT DISTINCT ON (prescription_id, medicine_id)
|
|---|
| 1616 | prescription_id,
|
|---|
| 1617 | medicine_id,
|
|---|
| 1618 | dosage,
|
|---|
| 1619 | num_days
|
|---|
| 1620 | FROM assigned
|
|---|
| 1621 | ORDER BY prescription_id, medicine_id, slot
|
|---|
| 1622 | )
|
|---|
| 1623 |
|
|---|
| 1624 | INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
|
|---|
| 1625 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 1626 | FROM deduped
|
|---|
| 1627 | ON CONFLICT (prescription_id, medicine_id) DO NOTHING;
|
|---|
| 1628 |
|
|---|
| 1629 | -- show prescriptions with their medicines
|
|---|
| 1630 | -- SELECT
|
|---|
| 1631 | -- pr.id AS prescription_id,
|
|---|
| 1632 | -- e.date_examination,
|
|---|
| 1633 | -- m.name AS medicine,
|
|---|
| 1634 | -- pm.dosage,
|
|---|
| 1635 | -- pm.num_days,
|
|---|
| 1636 | -- CASE WHEN m.shop_item_id IS NOT NULL THEN 'in shop' ELSE 'prescription only' END AS availability
|
|---|
| 1637 | -- FROM prescription pr
|
|---|
| 1638 | -- JOIN prescription_medicine pm ON pm.prescription_id = pr.id
|
|---|
| 1639 | -- JOIN medicine m ON m.id = pm.medicine_id
|
|---|
| 1640 | -- JOIN examination e ON e.id = pr.examination_id
|
|---|
| 1641 | -- ORDER BY pr.id, m.name
|
|---|
| 1642 | -- LIMIT 50;
|
|---|
| 1643 |
|
|---|
| 1644 |
|
|---|
| 1645 |
|
|---|
| 1646 | -- ============================================================
|
|---|
| 1647 | -- appointment (vaccination oriented)
|
|---|
| 1648 | -- ============================================================
|
|---|
| 1649 |
|
|---|
| 1650 | INSERT INTO appointment (date_appointment, reason, phone, owner_id, pet_id)
|
|---|
| 1651 | SELECT
|
|---|
| 1652 | CURRENT_DATE - (floor(random() * 730) + 1)::int AS date_appointment,
|
|---|
| 1653 | reason_list.reason,
|
|---|
| 1654 | o.phone,
|
|---|
| 1655 | o.id AS owner_id,
|
|---|
| 1656 | p.id AS pet_id
|
|---|
| 1657 | FROM owner o
|
|---|
| 1658 | JOIN LATERAL (
|
|---|
| 1659 | SELECT id
|
|---|
| 1660 | FROM pet
|
|---|
| 1661 | WHERE owner_id = o.id
|
|---|
| 1662 | ORDER BY random()
|
|---|
| 1663 | LIMIT 1
|
|---|
| 1664 | ) p ON true
|
|---|
| 1665 | CROSS JOIN LATERAL (
|
|---|
| 1666 | SELECT reason
|
|---|
| 1667 | FROM (VALUES
|
|---|
| 1668 | ('Annual vaccination'),
|
|---|
| 1669 | ('Rabies vaccine booster'),
|
|---|
| 1670 | ('Core vaccine schedule - puppy/kitten'),
|
|---|
| 1671 | ('Bordetella vaccination'),
|
|---|
| 1672 | ('Leptospirosis booster'),
|
|---|
| 1673 | ('Feline herpesvirus / calicivirus / panleukopenia combo'),
|
|---|
| 1674 | ('Canine distemper / parvovirus booster'),
|
|---|
| 1675 | ('Vaccine certificate needed for travel'),
|
|---|
| 1676 | ('First vaccination - new pet'),
|
|---|
| 1677 | ('Overdue vaccination catch-up')
|
|---|
| 1678 | ) AS r(reason)
|
|---|
| 1679 | WHERE o.id IS NOT NULL -- random per row
|
|---|
| 1680 | ORDER BY random()
|
|---|
| 1681 | LIMIT 1
|
|---|
| 1682 | ) reason_list;
|
|---|
| 1683 |
|
|---|
| 1684 | -- ============================================================
|
|---|
| 1685 | -- EXAMINATIONS for new appointments (~75% coverage)
|
|---|
| 1686 | -- date_examination >= date_appointment
|
|---|
| 1687 | -- employee_id - random vet with role_id = 2
|
|---|
| 1688 | -- examination_room_id - type = 'examination'
|
|---|
| 1689 | -- ============================================================
|
|---|
| 1690 |
|
|---|
| 1691 | INSERT INTO examination (date_examination, status, description, appointment_id, employee_id, examination_room_id)
|
|---|
| 1692 | SELECT
|
|---|
| 1693 | a.date_appointment + (floor(random() * 5))::int AS date_examination,
|
|---|
| 1694 |
|
|---|
| 1695 | CASE
|
|---|
| 1696 | WHEN random() < 0.78 THEN 'completed'
|
|---|
| 1697 | WHEN random() < 0.88 THEN 'scheduled'
|
|---|
| 1698 | ELSE 'cancelled'
|
|---|
| 1699 | END AS status,
|
|---|
| 1700 |
|
|---|
| 1701 | desc_list.description,
|
|---|
| 1702 | a.id AS appointment_id,
|
|---|
| 1703 |
|
|---|
| 1704 | emp.id AS employee_id,
|
|---|
| 1705 | r.id AS examination_room_id
|
|---|
| 1706 |
|
|---|
| 1707 | FROM appointment a
|
|---|
| 1708 | -- appointments that have no examination yet
|
|---|
| 1709 | LEFT JOIN examination e ON e.appointment_id = a.id
|
|---|
| 1710 | CROSS JOIN LATERAL (
|
|---|
| 1711 | SELECT description
|
|---|
| 1712 | FROM (VALUES
|
|---|
| 1713 | ('Pre-vaccination health check completed. Patient fit for immunisation.'),
|
|---|
| 1714 | ('Animal examined prior to vaccination. No contraindications found.'),
|
|---|
| 1715 | ('Vaccination visit. General condition assessed; vitals normal.'),
|
|---|
| 1716 | ('Patient presented for scheduled immunisation. Brief physical performed.'),
|
|---|
| 1717 | ('Health status confirmed satisfactory before vaccine administration.'),
|
|---|
| 1718 | ('Routine vaccination examination. Lymph nodes and temperature normal.'),
|
|---|
| 1719 | ('Owner updated on vaccine schedule. Patient in good overall condition.'),
|
|---|
| 1720 | ('Pre-vaccine check: skin, coat, mucous membranes all within normal limits.'),
|
|---|
| 1721 | ('Examination completed. Booster due; owner reminded of next schedule.'),
|
|---|
| 1722 | ('Young patient examined ahead of core vaccine series. No abnormalities.')
|
|---|
| 1723 | ) AS d(description)
|
|---|
| 1724 | WHERE a.id IS NOT NULL
|
|---|
| 1725 | ORDER BY random()
|
|---|
| 1726 | LIMIT 1
|
|---|
| 1727 | ) desc_list
|
|---|
| 1728 | -- random employee with role_id = 2
|
|---|
| 1729 | CROSS JOIN LATERAL (
|
|---|
| 1730 | SELECT id
|
|---|
| 1731 | FROM employee
|
|---|
| 1732 | WHERE role_id = 2
|
|---|
| 1733 | AND a.id IS NOT NULL
|
|---|
| 1734 | ORDER BY random()
|
|---|
| 1735 | LIMIT 1
|
|---|
| 1736 | ) emp
|
|---|
| 1737 | -- random room with type = 'examination'
|
|---|
| 1738 | CROSS JOIN LATERAL (
|
|---|
| 1739 | SELECT id
|
|---|
| 1740 | FROM examination_room
|
|---|
| 1741 | WHERE type = 'examination'
|
|---|
| 1742 | AND a.id IS NOT NULL
|
|---|
| 1743 | ORDER BY random()
|
|---|
| 1744 | LIMIT 1
|
|---|
| 1745 | ) r
|
|---|
| 1746 | WHERE e.id IS NULL -- no existing examination for this appointment
|
|---|
| 1747 | AND random() < 0.75; -- 75% appointments get an examination
|
|---|
| 1748 |
|
|---|
| 1749 |
|
|---|
| 1750 | -- ============================================================
|
|---|
| 1751 | -- treatment (vaccination type)
|
|---|
| 1752 | -- linked to completed examinations that don't already have
|
|---|
| 1753 | -- a vaccination treatment
|
|---|
| 1754 | -- ============================================================
|
|---|
| 1755 |
|
|---|
| 1756 | INSERT INTO treatment (date_treatment, notes, treatment_type_id, examination_id)
|
|---|
| 1757 | SELECT
|
|---|
| 1758 | e.date_examination + (floor(random() * 3))::int AS date_treatment,
|
|---|
| 1759 |
|
|---|
| 1760 | notes_list.notes,
|
|---|
| 1761 |
|
|---|
| 1762 | (SELECT id FROM treatment_type WHERE name = 'vaccination') AS treatment_type_id,
|
|---|
| 1763 |
|
|---|
| 1764 | e.id AS examination_id
|
|---|
| 1765 |
|
|---|
| 1766 | FROM examination e
|
|---|
| 1767 | CROSS JOIN LATERAL (
|
|---|
| 1768 | SELECT notes
|
|---|
| 1769 | FROM (VALUES
|
|---|
| 1770 | ('Core vaccine administered. No immediate adverse reaction observed.'),
|
|---|
| 1771 | ('Booster vaccination given. Owner advised to monitor for 24 hours.'),
|
|---|
| 1772 | ('Rabies vaccine administered. Certificate issued.'),
|
|---|
| 1773 | ('Puppy / kitten primary course vaccine given. Next dose scheduled.'),
|
|---|
| 1774 | ('Annual booster completed. Patient tolerated injection well.'),
|
|---|
| 1775 | ('Leptospirosis component included in this year''s booster.'),
|
|---|
| 1776 | ('Intranasal Bordetella vaccine administered without complication.'),
|
|---|
| 1777 | ('Combination vaccine given SC in right scruff. Patient calm throughout.'),
|
|---|
| 1778 | ('Travel vaccine record updated. International health certificate provided.'),
|
|---|
| 1779 | ('Catch-up vaccination completed. Full schedule now up to date.')
|
|---|
| 1780 | ) AS n(notes)
|
|---|
| 1781 | WHERE e.id IS NOT NULL
|
|---|
| 1782 | ORDER BY random()
|
|---|
| 1783 | LIMIT 1
|
|---|
| 1784 | ) notes_list
|
|---|
| 1785 | WHERE e.status = 'completed'
|
|---|
| 1786 | -- only those that don't already have a vaccination treatment
|
|---|
| 1787 | AND NOT EXISTS (
|
|---|
| 1788 | SELECT 1
|
|---|
| 1789 | FROM treatment t
|
|---|
| 1790 | JOIN treatment_type tt ON tt.id = t.treatment_type_id
|
|---|
| 1791 | WHERE t.examination_id = e.id
|
|---|
| 1792 | AND tt.name = 'vaccination'
|
|---|
| 1793 | );
|
|---|
| 1794 |
|
|---|
| 1795 |
|
|---|
| 1796 |
|
|---|
| 1797 | -- ============================================================
|
|---|
| 1798 | -- Shop categories, items, attributes, attribute values
|
|---|
| 1799 | -- ============================================================
|
|---|
| 1800 |
|
|---|
| 1801 |
|
|---|
| 1802 | -- ============================================================
|
|---|
| 1803 | -- shop_item_category
|
|---|
| 1804 | -- ============================================================
|
|---|
| 1805 |
|
|---|
| 1806 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1807 | VALUES ('Food', NULL)
|
|---|
| 1808 | ON CONFLICT DO NOTHING;
|
|---|
| 1809 |
|
|---|
| 1810 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1811 | SELECT 'Snacks', id FROM shop_item_category WHERE name = 'Food'
|
|---|
| 1812 | ON CONFLICT DO NOTHING;
|
|---|
| 1813 |
|
|---|
| 1814 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1815 | SELECT 'Supplements', id FROM shop_item_category WHERE name = 'Medicine'
|
|---|
| 1816 | ON CONFLICT DO NOTHING;
|
|---|
| 1817 |
|
|---|
| 1818 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1819 | VALUES ('Accessories', NULL)
|
|---|
| 1820 | ON CONFLICT DO NOTHING;
|
|---|
| 1821 |
|
|---|
| 1822 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1823 | SELECT 'Hygiene and Grooming', id FROM shop_item_category WHERE name = 'Pet Supplies'
|
|---|
| 1824 | ON CONFLICT DO NOTHING;
|
|---|
| 1825 |
|
|---|
| 1826 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1827 | SELECT 'Toys', id FROM shop_item_category WHERE name = 'Accessories'
|
|---|
| 1828 | ON CONFLICT DO NOTHING;
|
|---|
| 1829 |
|
|---|
| 1830 | INSERT INTO shop_item_category (name, parent_id)
|
|---|
| 1831 | VALUES ('Clothing', NULL)
|
|---|
| 1832 | ON CONFLICT DO NOTHING;
|
|---|
| 1833 |
|
|---|
| 1834 |
|
|---|
| 1835 | -- ============================================================
|
|---|
| 1836 | -- shop_item - Food
|
|---|
| 1837 | -- Foods for dogs, cats, birds, fish, reptiles, small mammals
|
|---|
| 1838 | -- ============================================================
|
|---|
| 1839 |
|
|---|
| 1840 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1841 | SELECT name, price, stock,
|
|---|
| 1842 | (SELECT id FROM shop_item_category WHERE name = 'Food')
|
|---|
| 1843 | FROM (VALUES
|
|---|
| 1844 | -- Dog food
|
|---|
| 1845 | ('Royal Canin Adult Dry Dog Food 15kg', 45.99, 80),
|
|---|
| 1846 | ('Hill''s Science Diet Puppy Chicken 12kg', 42.50, 60),
|
|---|
| 1847 | ('Purina Pro Plan Sensitive Salmon 7kg', 28.99, 75),
|
|---|
| 1848 | ('Orijen Original Dry Dog Food 6kg', 38.99, 50),
|
|---|
| 1849 | ('Pedigree Adult Wet Dog Food Beef 400g', 1.99, 300),
|
|---|
| 1850 | ('Cesar Classic Loaf with Chicken 150g', 1.49, 250),
|
|---|
| 1851 | ('Royal Canin Maxi Adult Dry Dog Food 10kg', 32.99, 70),
|
|---|
| 1852 | ('Eukanuba Adult Small Breed 3kg', 18.50, 90),
|
|---|
| 1853 |
|
|---|
| 1854 | -- Cat food
|
|---|
| 1855 | ('Royal Canin Indoor Adult Cat 4kg', 22.99, 100),
|
|---|
| 1856 | ('Hill''s Science Diet Adult Cat Chicken 3.5kg',20.99, 85),
|
|---|
| 1857 | ('Whiskas Adult Wet Cat Food Tuna 85g', 0.89, 400),
|
|---|
| 1858 | ('Purina Felix Adult Salmon Pouches 12x85g', 8.99, 120),
|
|---|
| 1859 | ('Orijen Cat & Kitten Dry Food 5.4kg', 44.99, 40),
|
|---|
| 1860 | ('Sheba Perfect Portions Chicken & Tuna 72g', 1.29, 350),
|
|---|
| 1861 | ('Royal Canin Kitten Dry Food 2kg', 15.99, 95),
|
|---|
| 1862 |
|
|---|
| 1863 | -- Bird food
|
|---|
| 1864 | ('Versele-Laga Prestige Parrot Mix 3kg', 12.99, 60),
|
|---|
| 1865 | ('Kaytee Forti-Diet Pro Canary Seed 2lb', 9.99, 55),
|
|---|
| 1866 | ('Zupreem Natural Pellets Medium Birds 1.25kg', 18.49, 45),
|
|---|
| 1867 | ('Vitakraft Budgie Seed Mix 1kg', 5.99, 80),
|
|---|
| 1868 | ('Harrisons Adult Lifetime Fine Pellets 454g', 17.99, 35),
|
|---|
| 1869 |
|
|---|
| 1870 | -- Fish food
|
|---|
| 1871 | ('Tetra Goldfish Flakes 200g', 6.49, 110),
|
|---|
| 1872 | ('Hikari Cichlid Gold Floating Pellets 342g', 12.99, 70),
|
|---|
| 1873 | ('Fluval Bug Bites Tropical Fish Food 45g', 9.99, 90),
|
|---|
| 1874 | ('API Tropical Flakes 71g', 5.49, 100),
|
|---|
| 1875 | ('Sera Vipan Nature Flake Food 250ml', 8.99, 85),
|
|---|
| 1876 |
|
|---|
| 1877 | -- Reptile food
|
|---|
| 1878 | ('Exo Terra Mealworms Canned Food 34g', 4.99, 60),
|
|---|
| 1879 | ('Zoo Med Can O'' Crickets 35g', 5.49, 55),
|
|---|
| 1880 | ('Flukers Freeze-Dried Crickets 1.2oz', 6.99, 50),
|
|---|
| 1881 | ('Repashy Crested Gecko MRP Banana 3oz', 12.49, 40),
|
|---|
| 1882 |
|
|---|
| 1883 | -- Small mammal food
|
|---|
| 1884 | ('Oxbow Essentials Adult Rabbit Pellets 5lb', 18.99, 65),
|
|---|
| 1885 | ('Supreme Science Selective Hamster 350g', 6.49, 75),
|
|---|
| 1886 | ('Kaytee Forti-Diet Guinea Pig Food 5lb', 12.99, 55),
|
|---|
| 1887 | ('Versele-Laga Complete Ferret 750g', 14.99, 45)
|
|---|
| 1888 | ) AS t(name, price, stock);
|
|---|
| 1889 |
|
|---|
| 1890 |
|
|---|
| 1891 | -- ============================================================
|
|---|
| 1892 | -- shop_item - Snacks
|
|---|
| 1893 | -- ============================================================
|
|---|
| 1894 |
|
|---|
| 1895 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1896 | SELECT name, price, stock,
|
|---|
| 1897 | (SELECT id FROM shop_item_category WHERE name = 'Snacks')
|
|---|
| 1898 | FROM (VALUES
|
|---|
| 1899 | -- Dog snacks
|
|---|
| 1900 | ('Milk-Bone Original Dog Biscuits 24oz', 7.99, 150),
|
|---|
| 1901 | ('Zuke''s Mini Naturals Chicken Treats 6oz', 8.49, 120),
|
|---|
| 1902 | ('Dentastix Daily Oral Care Medium 28 Sticks', 12.99, 100),
|
|---|
| 1903 | ('Greenies Original Dental Treats Large 12oz', 16.99, 85),
|
|---|
| 1904 | ('Wellness Soft WellBites Lamb & Salmon 6oz', 9.49, 95),
|
|---|
| 1905 | ('Merrick Power Bites Real Chicken 6oz', 8.99, 110),
|
|---|
| 1906 | ('Nylabones Puppy Chew Chicken Flavour', 5.99, 130),
|
|---|
| 1907 | ('Bully Sticks 6-inch Natural 10 Pack', 14.99, 70),
|
|---|
| 1908 |
|
|---|
| 1909 | -- Cat snacks
|
|---|
| 1910 | ('Temptations Classic Treats Chicken 85g', 2.99, 200),
|
|---|
| 1911 | ('Dreamies Cat Treats Cheese 60g', 1.99, 220),
|
|---|
| 1912 | ('Churu Purée Tuna with Salmon 4x14g', 4.49, 180),
|
|---|
| 1913 | ('Greenies Feline Dental Treats Ocean Fish 60g', 5.49, 110),
|
|---|
| 1914 | ('Whiskas Temptations Tuna 180g', 3.99, 150),
|
|---|
| 1915 |
|
|---|
| 1916 | -- Bird snacks
|
|---|
| 1917 | ('Vitakraft Crunch Stick Budgie Honey 2-pack', 3.49, 90),
|
|---|
| 1918 | ('Kaytee Fiesta Yogurt Dipped Papaya Bird Treat', 4.99, 70),
|
|---|
| 1919 |
|
|---|
| 1920 | -- Small mammal snacks
|
|---|
| 1921 | ('Oxbow Simple Rewards Timothy Hay Treats 3oz', 3.99, 85),
|
|---|
| 1922 | ('Supreme Tiny Friends Yogurt Drops Strawberry', 2.99, 95),
|
|---|
| 1923 | ('Kaytee Treat Stick Rabbit Honey & Oat', 2.49, 100)
|
|---|
| 1924 | ) AS t(name, price, stock);
|
|---|
| 1925 |
|
|---|
| 1926 |
|
|---|
| 1927 | -- ============================================================
|
|---|
| 1928 | -- shop_item - Supplements
|
|---|
| 1929 | -- ============================================================
|
|---|
| 1930 |
|
|---|
| 1931 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1932 | SELECT name, price, stock,
|
|---|
| 1933 | (SELECT id FROM shop_item_category WHERE name = 'Supplements')
|
|---|
| 1934 | FROM (VALUES
|
|---|
| 1935 | ('Zesty Paws Multivitamin Bites for Dogs 90ct', 24.99, 70),
|
|---|
| 1936 | ('VetriScience Canine Plus Senior Tabs 60ct', 19.99, 55),
|
|---|
| 1937 | ('Nutramax Cosequin DS Plus MSM 60ct', 29.99, 60),
|
|---|
| 1938 | ('Zesty Paws Omega Bites Wild Alaskan Fish Oil', 22.49, 65),
|
|---|
| 1939 | ('Vetri-Science Cell Advance 440 Cats 60ct', 18.99, 50),
|
|---|
| 1940 | ('Pet Naturals Daily Multi Cat 30ct', 9.99, 80),
|
|---|
| 1941 | ('Nutramax Proviable-DC Probiotic Caps 80ct', 27.99, 45),
|
|---|
| 1942 | ('Virbac C.E.T. Enzymatic Chews Medium Dogs', 21.99, 55),
|
|---|
| 1943 | ('Zesty Paws Mobility Bites Hip & Joint Dogs', 23.99, 60),
|
|---|
| 1944 | ('VetriScience Composure Calming Chews 30ct', 16.99, 70),
|
|---|
| 1945 | ('Oxbow Natural Science Vitamin C Tabs Guinea', 10.49, 85),
|
|---|
| 1946 | ('Rep-Cal Herptivite Reptile Multivitamin 3.3oz',14.99, 40),
|
|---|
| 1947 | ('Fluval Vita Tropical Fish Vitamin Drops 50ml', 8.99, 75),
|
|---|
| 1948 | ('Vetri-Science Feline Ultimate Probiotic 60ct', 21.99, 50)
|
|---|
| 1949 | ) AS t(name, price, stock);
|
|---|
| 1950 |
|
|---|
| 1951 |
|
|---|
| 1952 | -- ============================================================
|
|---|
| 1953 | -- shop_item - Accessories
|
|---|
| 1954 | -- ============================================================
|
|---|
| 1955 |
|
|---|
| 1956 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1957 | SELECT name, price, stock,
|
|---|
| 1958 | (SELECT id FROM shop_item_category WHERE name = 'Accessories')
|
|---|
| 1959 | FROM (VALUES
|
|---|
| 1960 | ('PetSafe Easy Walk Dog Harness Medium', 19.99, 90),
|
|---|
| 1961 | ('Ruffwear Front Range Harness Large', 39.99, 55),
|
|---|
| 1962 | ('Kong Classic Dog Toy Large', 13.99, 120),
|
|---|
| 1963 | ('Kurgo Tru-Fit Smart Dog Harness XL', 34.99, 45),
|
|---|
| 1964 | ('Flexi New Classic Retractable Leash 8m', 18.99, 100),
|
|---|
| 1965 | ('Rogz Reflective Dog Collar Medium', 9.99, 130),
|
|---|
| 1966 | ('Catit Flower Fountain 3L', 24.99, 75),
|
|---|
| 1967 | ('Trixie Cat Tree Tower 150cm', 69.99, 30),
|
|---|
| 1968 | ('PetSafe ScoopFree Automatic Litter Box', 99.99, 20),
|
|---|
| 1969 | ('AmazonBasics Elevated Cooling Dog Bed Large', 29.99, 60),
|
|---|
| 1970 | ('Midwest iCrate Single Door Dog Crate 30in', 49.99, 40),
|
|---|
| 1971 | ('Ferplast Favola Hamster Cage', 34.99, 35),
|
|---|
| 1972 | ('Zolux Birdcage Volière Sydney 105cm', 89.99, 15),
|
|---|
| 1973 | ('Exo Terra Terrarium 60x45x45cm', 139.99, 12),
|
|---|
| 1974 | ('Fluval Spec V Aquarium Kit 19L', 79.99, 20),
|
|---|
| 1975 | ('Catit Senses 2.0 Food Tree Puzzle', 18.99, 65),
|
|---|
| 1976 | ('Dog ID Tag Stainless Steel Bone Shape', 4.99, 200),
|
|---|
| 1977 | ('PetSafe Drinkwell Multi-Tier Fountain', 27.99, 50)
|
|---|
| 1978 | ) AS t(name, price, stock);
|
|---|
| 1979 |
|
|---|
| 1980 |
|
|---|
| 1981 | -- ============================================================
|
|---|
| 1982 | -- shop_item - Hygiene and Grooming
|
|---|
| 1983 | -- ============================================================
|
|---|
| 1984 |
|
|---|
| 1985 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 1986 | SELECT name, price, stock,
|
|---|
| 1987 | (SELECT id FROM shop_item_category WHERE name = 'Hygiene and Grooming')
|
|---|
| 1988 | FROM (VALUES
|
|---|
| 1989 | ('Tropiclean Natural Flea & Tick Dog Shampoo', 12.99, 90),
|
|---|
| 1990 | ('Burt''s Bees Hypoallergenic Dog Shampoo 16oz', 10.99, 85),
|
|---|
| 1991 | ('Virbac Epi-Soothe Oatmeal Shampoo 500ml', 18.99, 60),
|
|---|
| 1992 | ('Furminator deShedding Dog Shampoo 16oz', 14.99, 70),
|
|---|
| 1993 | ('Pet Head Feeling Flaky Anti-Dandruff Shampoo', 11.49, 65),
|
|---|
| 1994 | ('Chris Christensen Ice on Ice Conditioner 250ml',17.99, 45),
|
|---|
| 1995 | ('Furminator Long Hair deShedding Tool Large', 39.99, 55),
|
|---|
| 1996 | ('Andis EasyClip 2-Speed Dog Clipper Kit', 54.99, 30),
|
|---|
| 1997 | ('Wahl Bravura Lithium Dog Clipper', 84.99, 20),
|
|---|
| 1998 | ('Coastal Pet Safari Nail Clippers for Dogs', 9.99, 100),
|
|---|
| 1999 | ('Dremel PawControl Dog Nail Grinder Kit', 34.99, 40),
|
|---|
| 2000 | ('Virbac CET Oral Hygiene Kit Dog', 14.99, 75),
|
|---|
| 2001 | ('Pet Republique Dog Dental Wipes 100ct', 8.99, 90),
|
|---|
| 2002 | ('Douxo S3 PYO Antiseptic Mousse 150ml', 19.99, 50),
|
|---|
| 2003 | ('Veterinary Formula Clinical Care Ear Therapy', 9.99, 80),
|
|---|
| 2004 | ('Zymox Otic Ear Solution with Hydrocortisone', 18.99, 55),
|
|---|
| 2005 | ('Burt''s Bees Cat Hypoallergenic Shampoo 10oz', 9.99, 70),
|
|---|
| 2006 | ('Bio-Groom Super White Cat Shampoo 236ml', 11.49, 50),
|
|---|
| 2007 | ('Safari Cat Shedding Comb', 7.99, 85),
|
|---|
| 2008 | ('Hertzko Self-Cleaning Slicker Brush', 15.99, 95),
|
|---|
| 2009 | ('Pet Wipes Fragrance Free 100ct', 6.99, 120),
|
|---|
| 2010 | ('Tropiclean Fresh Breath Dog Water Additive', 10.49, 80)
|
|---|
| 2011 | ) AS t(name, price, stock);
|
|---|
| 2012 |
|
|---|
| 2013 |
|
|---|
| 2014 | -- ============================================================
|
|---|
| 2015 | -- shop_item - Toys
|
|---|
| 2016 | -- ============================================================
|
|---|
| 2017 |
|
|---|
| 2018 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 2019 | SELECT name, price, stock,
|
|---|
| 2020 | (SELECT id FROM shop_item_category WHERE name = 'Toys')
|
|---|
| 2021 | FROM (VALUES
|
|---|
| 2022 | -- Dog toys
|
|---|
| 2023 | ('Kong Extreme Dog Toy Large Black', 14.99, 100),
|
|---|
| 2024 | ('Chuckit! Ultra Ball Medium 2-Pack', 9.99, 120),
|
|---|
| 2025 | ('Outward Hound Hide-A-Squirrel Puzzle Large', 19.99, 70),
|
|---|
| 2026 | ('KONG Wobbler Interactive Treat Toy', 12.99, 85),
|
|---|
| 2027 | ('Tug-A-Jug Meal Dispensing Dog Toy', 14.49, 65),
|
|---|
| 2028 | ('Benebone Wishbone Chew Toy Bacon Large', 15.99, 90),
|
|---|
| 2029 | ('ZippyPaws Skinny Peltz Squeaky Plush 3-Pack', 11.99, 95),
|
|---|
| 2030 | ('iFetch Interactive Ball Launcher Small', 99.99, 25),
|
|---|
| 2031 |
|
|---|
| 2032 | -- Cat toys
|
|---|
| 2033 | ('Da Bird Feather Wand Cat Toy', 9.99, 110),
|
|---|
| 2034 | ('SmartyKat Hot Pursuit Electronic Cat Toy', 15.99, 75),
|
|---|
| 2035 | ('PetFusion Ambush Interactive Cat Toy', 24.99, 50),
|
|---|
| 2036 | ('Yeowww! Catnip Banana', 6.99, 130),
|
|---|
| 2037 | ('Catit Senses 2.0 Circuit Cat Toy', 17.99, 60),
|
|---|
| 2038 | ('Jackson Galaxy Air Wand Cat Toy', 9.49, 100),
|
|---|
| 2039 |
|
|---|
| 2040 | -- Bird toys
|
|---|
| 2041 | ('Super Bird Creations Booda Comfy Perch', 8.99, 55),
|
|---|
| 2042 | ('Prevue Hendryx Parrot Ladder Toy 12in', 7.49, 60),
|
|---|
| 2043 | ('Penn-Plax Bird Life Mirror with Bell', 5.99, 80),
|
|---|
| 2044 |
|
|---|
| 2045 | -- Small mammal toys
|
|---|
| 2046 | ('Niteangel Wooden Hamster Wheel 20cm Silent', 19.99, 50),
|
|---|
| 2047 | ('Kaytee Run-About 7in Clear Exercise Ball', 5.99, 85),
|
|---|
| 2048 | ('Ware Manufacturing Critter Tunnel Small', 7.99, 70),
|
|---|
| 2049 |
|
|---|
| 2050 | -- Fish / aquarium enrichment
|
|---|
| 2051 | ('Marina Aquarium Decoration Skull', 5.99, 90),
|
|---|
| 2052 | ('Penn-Plax Betta Hammock Leaf Ledge', 3.99, 110)
|
|---|
| 2053 | ) AS t(name, price, stock);
|
|---|
| 2054 |
|
|---|
| 2055 |
|
|---|
| 2056 | -- ============================================================
|
|---|
| 2057 | -- shop_item - Clothing
|
|---|
| 2058 | -- ============================================================
|
|---|
| 2059 |
|
|---|
| 2060 | INSERT INTO shop_item (name, price, stock, shop_item_category_id)
|
|---|
| 2061 | SELECT name, price, stock,
|
|---|
| 2062 | (SELECT id FROM shop_item_category WHERE name = 'Clothing')
|
|---|
| 2063 | FROM (VALUES
|
|---|
| 2064 | -- Hats
|
|---|
| 2065 | ('Casual Canine Cowboy Dog Hat Small', 8.99, 60),
|
|---|
| 2066 | ('Fido Finery Sun Protection Hat Medium', 12.99, 50),
|
|---|
| 2067 | ('Rubies Pet Shop Sailor Dog Hat S/M', 6.49, 70),
|
|---|
| 2068 |
|
|---|
| 2069 | -- Jackets / coats
|
|---|
| 2070 | ('Ruffwear Overcoat Fuse Dog Jacket XS', 79.99, 25),
|
|---|
| 2071 | ('Canada Pooch Puffer Vest Dog Jacket M', 44.99, 35),
|
|---|
| 2072 | ('Hurtta Expedition Parka Dog Winter Coat L', 89.99, 20),
|
|---|
| 2073 | ('Gooby Stretch Fleece Dog Vest Small', 18.99, 65),
|
|---|
| 2074 | ('Pinkaholic New York Bella Waterproof Coat M', 34.99, 40),
|
|---|
| 2075 | ('Zack & Zoey Nor''easter Dog Blanket Coat XL', 29.99, 30),
|
|---|
| 2076 |
|
|---|
| 2077 | -- Shoes / boots
|
|---|
| 2078 | ('Muttluks Fleece-Lined Dog Boots Set of 4 M', 39.99, 40),
|
|---|
| 2079 | ('Ruffwear Grip Trex Dog Boots Set of 4 S', 74.99, 25),
|
|---|
| 2080 | ('Ultra Paws Durable Dog Boots Set of 4 L', 29.99, 35),
|
|---|
| 2081 | ('Pawz Natural Rubber Dog Boots Medium 12ct', 16.99, 55),
|
|---|
| 2082 |
|
|---|
| 2083 | -- Recovery suits
|
|---|
| 2084 | ('Suitical Recovery Suit Dog XS Black', 29.99, 45),
|
|---|
| 2085 | ('Surgi-Snuggly Recovery Bodysuit Medium', 24.99, 50),
|
|---|
| 2086 | ('Buckeye Surgical Recovery Suit Cat/Small Dog', 22.99, 55),
|
|---|
| 2087 | ('iMatrix Recovery Suit Anti-Lick Vest Dog L', 34.99, 35)
|
|---|
| 2088 | ) AS t(name, price, stock);
|
|---|
| 2089 |
|
|---|
| 2090 |
|
|---|
| 2091 | -- ============================================================
|
|---|
| 2092 | -- shop_item_attribute - one set per category
|
|---|
| 2093 | -- ============================================================
|
|---|
| 2094 |
|
|---|
| 2095 | -- ---------- Food ----------
|
|---|
| 2096 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2097 | SELECT attr, dtype,
|
|---|
| 2098 | (SELECT id FROM shop_item_category WHERE name = 'Food')
|
|---|
| 2099 | FROM (VALUES
|
|---|
| 2100 | ('weight_kg', 'decimal'),
|
|---|
| 2101 | ('target_species', 'text'),
|
|---|
| 2102 | ('life_stage', 'text'),
|
|---|
| 2103 | ('flavour', 'text'),
|
|---|
| 2104 | ('grain_free', 'boolean'),
|
|---|
| 2105 | ('kcal_per_100g', 'integer')
|
|---|
| 2106 | ) AS t(attr, dtype);
|
|---|
| 2107 |
|
|---|
| 2108 | -- ---------- Snacks ----------
|
|---|
| 2109 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2110 | SELECT attr, dtype,
|
|---|
| 2111 | (SELECT id FROM shop_item_category WHERE name = 'Snacks')
|
|---|
| 2112 | FROM (VALUES
|
|---|
| 2113 | ('weight_g', 'decimal'),
|
|---|
| 2114 | ('target_species', 'text'),
|
|---|
| 2115 | ('flavour', 'text'),
|
|---|
| 2116 | ('primary_benefit', 'text'),
|
|---|
| 2117 | ('suitable_age', 'text')
|
|---|
| 2118 | ) AS t(attr, dtype);
|
|---|
| 2119 |
|
|---|
| 2120 | -- ---------- Supplements ----------
|
|---|
| 2121 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2122 | SELECT attr, dtype,
|
|---|
| 2123 | (SELECT id FROM shop_item_category WHERE name = 'Supplements')
|
|---|
| 2124 | FROM (VALUES
|
|---|
| 2125 | ('target_species', 'text'),
|
|---|
| 2126 | ('supplement_type', 'text'),
|
|---|
| 2127 | ('units_per_pack', 'integer'),
|
|---|
| 2128 | ('form', 'text'),
|
|---|
| 2129 | ('key_ingredient', 'text')
|
|---|
| 2130 | ) AS t(attr, dtype);
|
|---|
| 2131 |
|
|---|
| 2132 | -- ---------- Accessories ----------
|
|---|
| 2133 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2134 | SELECT attr, dtype,
|
|---|
| 2135 | (SELECT id FROM shop_item_category WHERE name = 'Accessories')
|
|---|
| 2136 | FROM (VALUES
|
|---|
| 2137 | ('target_species', 'text'),
|
|---|
| 2138 | ('size', 'text'),
|
|---|
| 2139 | ('material', 'text'),
|
|---|
| 2140 | ('colour', 'text'),
|
|---|
| 2141 | ('suitable_for', 'text')
|
|---|
| 2142 | ) AS t(attr, dtype);
|
|---|
| 2143 |
|
|---|
| 2144 | -- ---------- Hygiene and Grooming ----------
|
|---|
| 2145 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2146 | SELECT attr, dtype,
|
|---|
| 2147 | (SELECT id FROM shop_item_category WHERE name = 'Hygiene and Grooming')
|
|---|
| 2148 | FROM (VALUES
|
|---|
| 2149 | ('target_species', 'text'),
|
|---|
| 2150 | ('product_type', 'text'),
|
|---|
| 2151 | ('volume_ml', 'decimal'),
|
|---|
| 2152 | ('key_ingredient', 'text'),
|
|---|
| 2153 | ('scent', 'text')
|
|---|
| 2154 | ) AS t(attr, dtype);
|
|---|
| 2155 |
|
|---|
| 2156 | -- ---------- Toys ----------
|
|---|
| 2157 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2158 | SELECT attr, dtype,
|
|---|
| 2159 | (SELECT id FROM shop_item_category WHERE name = 'Toys')
|
|---|
| 2160 | FROM (VALUES
|
|---|
| 2161 | ('target_species', 'text'),
|
|---|
| 2162 | ('size', 'text'),
|
|---|
| 2163 | ('material', 'text'),
|
|---|
| 2164 | ('interactive', 'boolean'),
|
|---|
| 2165 | ('primary_activity', 'text')
|
|---|
| 2166 | ) AS t(attr, dtype);
|
|---|
| 2167 |
|
|---|
| 2168 | -- ---------- Clothing ----------
|
|---|
| 2169 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2170 | SELECT attr, dtype,
|
|---|
| 2171 | (SELECT id FROM shop_item_category WHERE name = 'Clothing')
|
|---|
| 2172 | FROM (VALUES
|
|---|
| 2173 | ('target_species', 'text'),
|
|---|
| 2174 | ('size', 'text'),
|
|---|
| 2175 | ('material', 'text'),
|
|---|
| 2176 | ('colour', 'text'),
|
|---|
| 2177 | ('clothing_type', 'text'),
|
|---|
| 2178 | ('waterproof', 'boolean')
|
|---|
| 2179 | ) AS t(attr, dtype);
|
|---|
| 2180 |
|
|---|
| 2181 | -- ---------- Medicine ----------
|
|---|
| 2182 | INSERT INTO shop_item_attribute (name, data_type, shop_item_category_id)
|
|---|
| 2183 | SELECT attr, dtype,
|
|---|
| 2184 | (SELECT id FROM shop_item_category WHERE name = 'Medicine')
|
|---|
| 2185 | FROM (VALUES
|
|---|
| 2186 | ('dosage_form', 'text'),
|
|---|
| 2187 | ('strength', 'text'),
|
|---|
| 2188 | ('pack_size', 'integer'),
|
|---|
| 2189 | ('prescription_only','boolean'),
|
|---|
| 2190 | ('target_species', 'text')
|
|---|
| 2191 | ) AS t(attr, dtype);
|
|---|
| 2192 |
|
|---|
| 2193 |
|
|---|
| 2194 | -- ============================================================
|
|---|
| 2195 | -- shop_item_attribute_value
|
|---|
| 2196 | -- One value per (item x attribute) for all items in each category.
|
|---|
| 2197 | -- ============================================================
|
|---|
| 2198 |
|
|---|
| 2199 | -- ----------------------------------------------------------------
|
|---|
| 2200 | -- Helper: map every shop_item in 'Food' to its attribute values
|
|---|
| 2201 | -- ----------------------------------------------------------------
|
|---|
| 2202 |
|
|---|
| 2203 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2204 | SELECT final_val.val, a.id, si.id
|
|---|
| 2205 | FROM shop_item si
|
|---|
| 2206 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Food'
|
|---|
| 2207 | CROSS JOIN LATERAL (
|
|---|
| 2208 | SELECT
|
|---|
| 2209 | CASE
|
|---|
| 2210 | WHEN si.name ILIKE '%15kg%' OR si.name ILIKE '%12kg%' OR si.name ILIKE '%10kg%'
|
|---|
| 2211 | THEN regexp_replace(si.name, '.*?(\d+(?:\.\d+)?)\s*kg.*', '\1')
|
|---|
| 2212 | WHEN si.name ILIKE '%7kg%' THEN '7'
|
|---|
| 2213 | WHEN si.name ILIKE '%6kg%' THEN '6'
|
|---|
| 2214 | WHEN si.name ILIKE '%5.4kg%'THEN '5.4'
|
|---|
| 2215 | WHEN si.name ILIKE '%4kg%' THEN '4'
|
|---|
| 2216 | WHEN si.name ILIKE '%3.5kg%'THEN '3.5'
|
|---|
| 2217 | WHEN si.name ILIKE '%2kg%' THEN '2'
|
|---|
| 2218 | WHEN si.name ILIKE '%5lb%' THEN '2.27'
|
|---|
| 2219 | WHEN si.name ILIKE '%2lb%' THEN '0.91'
|
|---|
| 2220 | WHEN si.name ILIKE '%400g%' THEN '0.4'
|
|---|
| 2221 | WHEN si.name ILIKE '%454g%' THEN '0.454'
|
|---|
| 2222 | WHEN si.name ILIKE '%750g%' THEN '0.75'
|
|---|
| 2223 | WHEN si.name ILIKE '%350g%' THEN '0.35'
|
|---|
| 2224 | WHEN si.name ILIKE '%250ml%'OR si.name ILIKE '%250g%' THEN '0.25'
|
|---|
| 2225 | WHEN si.name ILIKE '%150g%' THEN '0.15'
|
|---|
| 2226 | ELSE '0.5'
|
|---|
| 2227 | END AS weight_kg,
|
|---|
| 2228 |
|
|---|
| 2229 | CASE
|
|---|
| 2230 | WHEN si.name ILIKE '%dog%' OR si.name ILIKE '%pedigree%' OR si.name ILIKE '%cesar%'
|
|---|
| 2231 | OR si.name ILIKE '%orijen%' AND si.name NOT ILIKE '%cat%'
|
|---|
| 2232 | OR si.name ILIKE '%eukanuba%' THEN 'Dog'
|
|---|
| 2233 | WHEN si.name ILIKE '%cat%' OR si.name ILIKE '%whiskas%' OR si.name ILIKE '%felix%'
|
|---|
| 2234 | OR si.name ILIKE '%sheba%' THEN 'Cat'
|
|---|
| 2235 | WHEN si.name ILIKE '%parrot%' OR si.name ILIKE '%canary%' OR si.name ILIKE '%budgie%'
|
|---|
| 2236 | OR si.name ILIKE '%bird%' OR si.name ILIKE '%pellets%' AND si.name ILIKE '%birds%' THEN 'Bird'
|
|---|
| 2237 | WHEN si.name ILIKE '%goldfish%' OR si.name ILIKE '%cichlid%' OR si.name ILIKE '%tropical%'
|
|---|
| 2238 | OR si.name ILIKE '%flake%' OR si.name ILIKE '%bug bites%' OR si.name ILIKE '%vipan%' THEN 'Fish'
|
|---|
| 2239 | WHEN si.name ILIKE '%mealworm%' OR si.name ILIKE '%cricket%' OR si.name ILIKE '%crested gecko%'
|
|---|
| 2240 | OR si.name ILIKE '%reptile%' THEN 'Reptile'
|
|---|
| 2241 | WHEN si.name ILIKE '%rabbit%' OR si.name ILIKE '%hamster%' OR si.name ILIKE '%guinea pig%'
|
|---|
| 2242 | OR si.name ILIKE '%ferret%' THEN 'Small Mammal'
|
|---|
| 2243 | ELSE 'Multi-species'
|
|---|
| 2244 | END AS target_species,
|
|---|
| 2245 |
|
|---|
| 2246 | CASE
|
|---|
| 2247 | WHEN si.name ILIKE '%puppy%' OR si.name ILIKE '%kitten%' THEN 'Puppy/Kitten'
|
|---|
| 2248 | WHEN si.name ILIKE '%senior%' OR si.name ILIKE '%mature%' THEN 'Senior'
|
|---|
| 2249 | ELSE 'Adult'
|
|---|
| 2250 | END AS life_stage,
|
|---|
| 2251 |
|
|---|
| 2252 | CASE
|
|---|
| 2253 | WHEN si.name ILIKE '%salmon%' THEN 'Salmon'
|
|---|
| 2254 | WHEN si.name ILIKE '%chicken%' THEN 'Chicken'
|
|---|
| 2255 | WHEN si.name ILIKE '%beef%' THEN 'Beef'
|
|---|
| 2256 | WHEN si.name ILIKE '%tuna%' THEN 'Tuna'
|
|---|
| 2257 | WHEN si.name ILIKE '%banana%' THEN 'Banana'
|
|---|
| 2258 | WHEN si.name ILIKE '%honey%' THEN 'Honey'
|
|---|
| 2259 | WHEN si.name ILIKE '%papaya%' THEN 'Papaya'
|
|---|
| 2260 | ELSE 'Mixed'
|
|---|
| 2261 | END AS flavour,
|
|---|
| 2262 |
|
|---|
| 2263 | CASE
|
|---|
| 2264 | WHEN si.name ILIKE '%orijen%' OR si.name ILIKE '%grain free%' THEN 'true'
|
|---|
| 2265 | ELSE 'false'
|
|---|
| 2266 | END AS grain_free,
|
|---|
| 2267 |
|
|---|
| 2268 | CASE
|
|---|
| 2269 | WHEN si.name ILIKE '%wet%' OR si.name ILIKE '%loaf%'
|
|---|
| 2270 | OR si.name ILIKE '%400g%' OR si.name ILIKE '%150g%'
|
|---|
| 2271 | OR si.name ILIKE '%85g%' OR si.name ILIKE '%canned%' THEN '95'
|
|---|
| 2272 | WHEN si.name ILIKE '%orijen%' THEN '398'
|
|---|
| 2273 | ELSE '340'
|
|---|
| 2274 | END AS kcal_per_100g
|
|---|
| 2275 | ) v(weight_kg, target_species, life_stage, flavour, grain_free, kcal_per_100g)
|
|---|
| 2276 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2277 | CROSS JOIN LATERAL (
|
|---|
| 2278 | SELECT
|
|---|
| 2279 | CASE a.name
|
|---|
| 2280 | WHEN 'weight_kg' THEN v.weight_kg
|
|---|
| 2281 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2282 | WHEN 'life_stage' THEN v.life_stage
|
|---|
| 2283 | WHEN 'flavour' THEN v.flavour
|
|---|
| 2284 | WHEN 'grain_free' THEN v.grain_free
|
|---|
| 2285 | WHEN 'kcal_per_100g' THEN v.kcal_per_100g
|
|---|
| 2286 | END AS val
|
|---|
| 2287 | ) final_val(val)
|
|---|
| 2288 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2289 |
|
|---|
| 2290 |
|
|---|
| 2291 | -- ----------------------------------------------------------------
|
|---|
| 2292 | -- Snacks attribute values
|
|---|
| 2293 | -- ----------------------------------------------------------------
|
|---|
| 2294 |
|
|---|
| 2295 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2296 | SELECT final_val.val, a.id, si.id
|
|---|
| 2297 | FROM shop_item si
|
|---|
| 2298 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Snacks'
|
|---|
| 2299 | CROSS JOIN LATERAL (
|
|---|
| 2300 | SELECT
|
|---|
| 2301 | CASE
|
|---|
| 2302 | WHEN si.name ILIKE '%24oz%' THEN '680'
|
|---|
| 2303 | WHEN si.name ILIKE '%12oz%' THEN '340'
|
|---|
| 2304 | WHEN si.name ILIKE '%6oz%' THEN '170'
|
|---|
| 2305 | WHEN si.name ILIKE '%85g%' THEN '85'
|
|---|
| 2306 | WHEN si.name ILIKE '%60g%' THEN '60'
|
|---|
| 2307 | WHEN si.name ILIKE '%180g%' THEN '180'
|
|---|
| 2308 | WHEN si.name ILIKE '%3oz%' THEN '85'
|
|---|
| 2309 | ELSE '100'
|
|---|
| 2310 | END AS weight_g,
|
|---|
| 2311 |
|
|---|
| 2312 | CASE
|
|---|
| 2313 | WHEN si.name ILIKE '%dog%' OR si.name ILIKE '%milk-bone%' OR si.name ILIKE '%dentastix%'
|
|---|
| 2314 | OR si.name ILIKE '%greenies%' AND si.name NOT ILIKE '%feline%'
|
|---|
| 2315 | OR si.name ILIKE '%bully%' OR si.name ILIKE '%nylabone%'
|
|---|
| 2316 | OR si.name ILIKE '%wellbite%' OR si.name ILIKE '%merrick%' THEN 'Dog'
|
|---|
| 2317 | WHEN si.name ILIKE '%cat%' OR si.name ILIKE '%temptation%' OR si.name ILIKE '%dreamies%'
|
|---|
| 2318 | OR si.name ILIKE '%churu%' OR si.name ILIKE '%feline%' OR si.name ILIKE '%whiskas%' THEN 'Cat'
|
|---|
| 2319 | WHEN si.name ILIKE '%budgie%' OR si.name ILIKE '%bird%' OR si.name ILIKE '%crunch stick%' THEN 'Bird'
|
|---|
| 2320 | WHEN si.name ILIKE '%rabbit%' OR si.name ILIKE '%hamster%' OR si.name ILIKE '%guinea%'
|
|---|
| 2321 | OR si.name ILIKE '%tiny friends%' OR si.name ILIKE '%oxbow%' THEN 'Small Mammal'
|
|---|
| 2322 | ELSE 'Multi-species'
|
|---|
| 2323 | END AS target_species,
|
|---|
| 2324 |
|
|---|
| 2325 | CASE
|
|---|
| 2326 | WHEN si.name ILIKE '%chicken%' THEN 'Chicken'
|
|---|
| 2327 | WHEN si.name ILIKE '%salmon%' THEN 'Salmon'
|
|---|
| 2328 | WHEN si.name ILIKE '%lamb%' THEN 'Lamb'
|
|---|
| 2329 | WHEN si.name ILIKE '%tuna%' THEN 'Tuna'
|
|---|
| 2330 | WHEN si.name ILIKE '%cheese%' THEN 'Cheese'
|
|---|
| 2331 | WHEN si.name ILIKE '%bacon%' THEN 'Bacon'
|
|---|
| 2332 | WHEN si.name ILIKE '%honey%' THEN 'Honey & Oat'
|
|---|
| 2333 | WHEN si.name ILIKE '%strawberry%' THEN 'Strawberry'
|
|---|
| 2334 | WHEN si.name ILIKE '%papaya%' THEN 'Papaya'
|
|---|
| 2335 | ELSE 'Mixed'
|
|---|
| 2336 | END AS flavour,
|
|---|
| 2337 |
|
|---|
| 2338 | CASE
|
|---|
| 2339 | WHEN si.name ILIKE '%dental%' OR si.name ILIKE '%dentastix%' OR si.name ILIKE '%greenies%' THEN 'Dental health'
|
|---|
| 2340 | WHEN si.name ILIKE '%churu%' THEN 'Hydration & palatability'
|
|---|
| 2341 | WHEN si.name ILIKE '%bully%' THEN 'Mental stimulation & chewing'
|
|---|
| 2342 | WHEN si.name ILIKE '%nylabone%' THEN 'Chewing & teething'
|
|---|
| 2343 | ELSE 'Reward & training'
|
|---|
| 2344 | END AS primary_benefit,
|
|---|
| 2345 |
|
|---|
| 2346 | CASE
|
|---|
| 2347 | WHEN si.name ILIKE '%puppy%' OR si.name ILIKE '%kitten%' THEN 'Puppy/Kitten'
|
|---|
| 2348 | WHEN si.name ILIKE '%senior%' THEN 'Senior'
|
|---|
| 2349 | ELSE 'All ages'
|
|---|
| 2350 | END AS suitable_age
|
|---|
| 2351 | ) v(weight_g, target_species, flavour, primary_benefit, suitable_age)
|
|---|
| 2352 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2353 | CROSS JOIN LATERAL (
|
|---|
| 2354 | SELECT CASE a.name
|
|---|
| 2355 | WHEN 'weight_g' THEN v.weight_g
|
|---|
| 2356 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2357 | WHEN 'flavour' THEN v.flavour
|
|---|
| 2358 | WHEN 'primary_benefit' THEN v.primary_benefit
|
|---|
| 2359 | WHEN 'suitable_age' THEN v.suitable_age
|
|---|
| 2360 | END AS val
|
|---|
| 2361 | ) final_val(val)
|
|---|
| 2362 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2363 |
|
|---|
| 2364 |
|
|---|
| 2365 | -- ----------------------------------------------------------------
|
|---|
| 2366 | -- Supplements attribute values
|
|---|
| 2367 | -- ----------------------------------------------------------------
|
|---|
| 2368 |
|
|---|
| 2369 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2370 | SELECT final_val.val, a.id, si.id
|
|---|
| 2371 | FROM shop_item si
|
|---|
| 2372 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Supplements'
|
|---|
| 2373 | CROSS JOIN LATERAL (
|
|---|
| 2374 | SELECT
|
|---|
| 2375 | CASE
|
|---|
| 2376 | WHEN si.name ILIKE '%dog%' OR si.name ILIKE '%canine%' THEN 'Dog'
|
|---|
| 2377 | WHEN si.name ILIKE '%cat%' OR si.name ILIKE '%feline%' THEN 'Cat'
|
|---|
| 2378 | WHEN si.name ILIKE '%guinea%' THEN 'Guinea Pig'
|
|---|
| 2379 | WHEN si.name ILIKE '%reptile%' THEN 'Reptile'
|
|---|
| 2380 | WHEN si.name ILIKE '%fish%' OR si.name ILIKE '%tropical%' THEN 'Fish'
|
|---|
| 2381 | ELSE 'Multi-species'
|
|---|
| 2382 | END AS target_species,
|
|---|
| 2383 |
|
|---|
| 2384 | CASE
|
|---|
| 2385 | WHEN si.name ILIKE '%multivitamin%' OR si.name ILIKE '%multi%' OR si.name ILIKE '%vita%' THEN 'Multivitamin'
|
|---|
| 2386 | WHEN si.name ILIKE '%omega%' OR si.name ILIKE '%fish oil%' THEN 'Omega-3 / EFA'
|
|---|
| 2387 | WHEN si.name ILIKE '%cosequin%' OR si.name ILIKE '%mobility%' OR si.name ILIKE '%joint%' THEN 'Joint support'
|
|---|
| 2388 | WHEN si.name ILIKE '%probiotic%' THEN 'Probiotic'
|
|---|
| 2389 | WHEN si.name ILIKE '%calming%' OR si.name ILIKE '%composure%' THEN 'Calming / stress'
|
|---|
| 2390 | WHEN si.name ILIKE '%dental%' OR si.name ILIKE '%enzymatic%' THEN 'Dental health'
|
|---|
| 2391 | WHEN si.name ILIKE '%vitamin c%' THEN 'Vitamin C'
|
|---|
| 2392 | ELSE 'General health'
|
|---|
| 2393 | END AS supplement_type,
|
|---|
| 2394 |
|
|---|
| 2395 | CASE
|
|---|
| 2396 | WHEN si.name ILIKE '%90ct%' THEN '90'
|
|---|
| 2397 | WHEN si.name ILIKE '%80ct%' THEN '80'
|
|---|
| 2398 | WHEN si.name ILIKE '%60ct%' THEN '60'
|
|---|
| 2399 | WHEN si.name ILIKE '%30ct%' THEN '30'
|
|---|
| 2400 | ELSE '60'
|
|---|
| 2401 | END AS units_per_pack,
|
|---|
| 2402 |
|
|---|
| 2403 | CASE
|
|---|
| 2404 | WHEN si.name ILIKE '%bites%' OR si.name ILIKE '%chews%' THEN 'Soft chew'
|
|---|
| 2405 | WHEN si.name ILIKE '%tabs%' OR si.name ILIKE '%tabs%' THEN 'Tablet'
|
|---|
| 2406 | WHEN si.name ILIKE '%caps%' OR si.name ILIKE '%capsule%' THEN 'Capsule'
|
|---|
| 2407 | WHEN si.name ILIKE '%drops%' THEN 'Liquid drops'
|
|---|
| 2408 | WHEN si.name ILIKE '%powder%' THEN 'Powder'
|
|---|
| 2409 | ELSE 'Tablet'
|
|---|
| 2410 | END AS form,
|
|---|
| 2411 |
|
|---|
| 2412 | CASE
|
|---|
| 2413 | WHEN si.name ILIKE '%omega%' OR si.name ILIKE '%fish oil%' THEN 'EPA & DHA'
|
|---|
| 2414 | WHEN si.name ILIKE '%cosequin%' OR si.name ILIKE '%joint%' THEN 'Glucosamine & Chondroitin'
|
|---|
| 2415 | WHEN si.name ILIKE '%probiotic%' THEN 'Lactobacillus acidophilus'
|
|---|
| 2416 | WHEN si.name ILIKE '%vitamin c%' THEN 'Ascorbic acid'
|
|---|
| 2417 | WHEN si.name ILIKE '%calming%' THEN 'L-Theanine & B vitamins'
|
|---|
| 2418 | ELSE 'Vitamins A, D3, E, B-complex'
|
|---|
| 2419 | END AS key_ingredient
|
|---|
| 2420 | ) v(target_species, supplement_type, units_per_pack, form, key_ingredient)
|
|---|
| 2421 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2422 | CROSS JOIN LATERAL (
|
|---|
| 2423 | SELECT CASE a.name
|
|---|
| 2424 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2425 | WHEN 'supplement_type' THEN v.supplement_type
|
|---|
| 2426 | WHEN 'units_per_pack' THEN v.units_per_pack
|
|---|
| 2427 | WHEN 'form' THEN v.form
|
|---|
| 2428 | WHEN 'key_ingredient' THEN v.key_ingredient
|
|---|
| 2429 | END AS val
|
|---|
| 2430 | ) final_val(val)
|
|---|
| 2431 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2432 |
|
|---|
| 2433 |
|
|---|
| 2434 | -- ----------------------------------------------------------------
|
|---|
| 2435 | -- Accessories attribute values
|
|---|
| 2436 | -- ----------------------------------------------------------------
|
|---|
| 2437 |
|
|---|
| 2438 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2439 | SELECT final_val.val, a.id, si.id
|
|---|
| 2440 | FROM shop_item si
|
|---|
| 2441 | JOIN shop_item_category sic
|
|---|
| 2442 | ON sic.id = si.shop_item_category_id
|
|---|
| 2443 | AND sic.name = 'Accessories'
|
|---|
| 2444 |
|
|---|
| 2445 | CROSS JOIN LATERAL (
|
|---|
| 2446 | SELECT
|
|---|
| 2447 | CASE
|
|---|
| 2448 | WHEN si.name ILIKE '%dog%'
|
|---|
| 2449 | OR si.name ILIKE '%canine%'
|
|---|
| 2450 | OR si.name ILIKE '%harness%'
|
|---|
| 2451 | OR si.name ILIKE '%leash%'
|
|---|
| 2452 | OR si.name ILIKE '%crate%'
|
|---|
| 2453 | OR si.name ILIKE '%cooling bed%'
|
|---|
| 2454 | THEN 'Dog'
|
|---|
| 2455 |
|
|---|
| 2456 | WHEN si.name ILIKE '%cat%'
|
|---|
| 2457 | OR si.name ILIKE '%litter%'
|
|---|
| 2458 | OR si.name ILIKE '%catit%'
|
|---|
| 2459 | OR si.name ILIKE '%cat tree%'
|
|---|
| 2460 | THEN 'Cat'
|
|---|
| 2461 |
|
|---|
| 2462 | WHEN si.name ILIKE '%hamster%'
|
|---|
| 2463 | OR si.name ILIKE '%favola%'
|
|---|
| 2464 | THEN 'Hamster'
|
|---|
| 2465 |
|
|---|
| 2466 | WHEN si.name ILIKE '%bird%'
|
|---|
| 2467 | OR si.name ILIKE '%volière%'
|
|---|
| 2468 | OR si.name ILIKE '%birdcage%'
|
|---|
| 2469 | THEN 'Bird'
|
|---|
| 2470 |
|
|---|
| 2471 | WHEN si.name ILIKE '%terrarium%'
|
|---|
| 2472 | OR si.name ILIKE '%exo terra%'
|
|---|
| 2473 | THEN 'Reptile'
|
|---|
| 2474 |
|
|---|
| 2475 | WHEN si.name ILIKE '%aquarium%'
|
|---|
| 2476 | OR si.name ILIKE '%fluval spec%'
|
|---|
| 2477 | THEN 'Fish'
|
|---|
| 2478 |
|
|---|
| 2479 | ELSE 'Multi-species'
|
|---|
| 2480 | END AS target_species,
|
|---|
| 2481 |
|
|---|
| 2482 | CASE
|
|---|
| 2483 | WHEN si.name ILIKE '%xsmall%'
|
|---|
| 2484 | OR si.name ILIKE '%xs%'
|
|---|
| 2485 | OR si.name ILIKE '%extra small%'
|
|---|
| 2486 | THEN 'XS'
|
|---|
| 2487 |
|
|---|
| 2488 | WHEN si.name ILIKE '%small%'
|
|---|
| 2489 | OR si.name ILIKE '% s %'
|
|---|
| 2490 | THEN 'S'
|
|---|
| 2491 |
|
|---|
| 2492 | WHEN si.name ILIKE '%medium%'
|
|---|
| 2493 | OR si.name ILIKE '% m %'
|
|---|
| 2494 | THEN 'M'
|
|---|
| 2495 |
|
|---|
| 2496 | WHEN si.name ILIKE '%large%'
|
|---|
| 2497 | OR si.name ILIKE '% l %'
|
|---|
| 2498 | OR si.name ILIKE '% xl%'
|
|---|
| 2499 | THEN 'L'
|
|---|
| 2500 |
|
|---|
| 2501 | ELSE 'Universal'
|
|---|
| 2502 | END AS size,
|
|---|
| 2503 |
|
|---|
| 2504 | CASE
|
|---|
| 2505 | WHEN si.name ILIKE '%nylon%' THEN 'Nylon'
|
|---|
| 2506 | WHEN si.name ILIKE '%leather%' THEN 'Leather'
|
|---|
| 2507 | WHEN si.name ILIKE '%metal%'
|
|---|
| 2508 | OR si.name ILIKE '%stainless%' THEN 'Stainless steel'
|
|---|
| 2509 | WHEN si.name ILIKE '%plastic%' THEN 'Plastic'
|
|---|
| 2510 | WHEN si.name ILIKE '%wire%'
|
|---|
| 2511 | OR si.name ILIKE '%crate%' THEN 'Steel wire'
|
|---|
| 2512 | WHEN si.name ILIKE '%wood%'
|
|---|
| 2513 | OR si.name ILIKE '%tree%' THEN 'Sisal & wood'
|
|---|
| 2514 | ELSE 'Mixed materials'
|
|---|
| 2515 | END AS material,
|
|---|
| 2516 |
|
|---|
| 2517 | CASE
|
|---|
| 2518 | WHEN si.name ILIKE '%black%' THEN 'Black'
|
|---|
| 2519 | WHEN si.name ILIKE '%red%' THEN 'Red'
|
|---|
| 2520 | WHEN si.name ILIKE '%blue%' THEN 'Blue'
|
|---|
| 2521 | ELSE 'Assorted'
|
|---|
| 2522 | END AS colour,
|
|---|
| 2523 |
|
|---|
| 2524 | CASE
|
|---|
| 2525 | WHEN si.name ILIKE '%fountain%' THEN 'Hydration'
|
|---|
| 2526 | WHEN si.name ILIKE '%harness%' THEN 'Walking / control'
|
|---|
| 2527 | WHEN si.name ILIKE '%leash%'
|
|---|
| 2528 | OR si.name ILIKE '%lead%' THEN 'Walking / restraint'
|
|---|
| 2529 | WHEN si.name ILIKE '%collar%' THEN 'Identification & control'
|
|---|
| 2530 | WHEN si.name ILIKE '%crate%' THEN 'Containment & transport'
|
|---|
| 2531 | WHEN si.name ILIKE '%bed%' THEN 'Rest & comfort'
|
|---|
| 2532 | WHEN si.name ILIKE '%litter%' THEN 'Hygiene'
|
|---|
| 2533 | WHEN si.name ILIKE '%cage%'
|
|---|
| 2534 | OR si.name ILIKE '%terrarium%'
|
|---|
| 2535 | OR si.name ILIKE '%aquarium%'
|
|---|
| 2536 | THEN 'Housing'
|
|---|
| 2537 | WHEN si.name ILIKE '%puzzle%'
|
|---|
| 2538 | OR si.name ILIKE '%food tree%'
|
|---|
| 2539 | THEN 'Enrichment & feeding'
|
|---|
| 2540 | ELSE 'General accessory'
|
|---|
| 2541 | END AS suitable_for
|
|---|
| 2542 |
|
|---|
| 2543 | ) v(target_species, size, material, colour, suitable_for)
|
|---|
| 2544 |
|
|---|
| 2545 | JOIN shop_item_attribute a
|
|---|
| 2546 | ON a.shop_item_category_id = sic.id
|
|---|
| 2547 |
|
|---|
| 2548 | CROSS JOIN LATERAL (
|
|---|
| 2549 | SELECT CASE a.name
|
|---|
| 2550 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2551 | WHEN 'size' THEN v.size
|
|---|
| 2552 | WHEN 'material' THEN v.material
|
|---|
| 2553 | WHEN 'colour' THEN v.colour
|
|---|
| 2554 | WHEN 'suitable_for' THEN v.suitable_for
|
|---|
| 2555 | END AS val
|
|---|
| 2556 | ) final_val(val)
|
|---|
| 2557 |
|
|---|
| 2558 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2559 |
|
|---|
| 2560 |
|
|---|
| 2561 | -- ----------------------------------------------------------------
|
|---|
| 2562 | -- Hygiene and Grooming attribute values
|
|---|
| 2563 | -- ----------------------------------------------------------------
|
|---|
| 2564 |
|
|---|
| 2565 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2566 | SELECT final_val.val, a.id, si.id
|
|---|
| 2567 | FROM shop_item si
|
|---|
| 2568 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Hygiene and Grooming'
|
|---|
| 2569 | CROSS JOIN LATERAL (
|
|---|
| 2570 | SELECT
|
|---|
| 2571 | CASE
|
|---|
| 2572 | WHEN si.name ILIKE '%cat%' THEN 'Cat'
|
|---|
| 2573 | WHEN si.name ILIKE '%dog%' OR si.name ILIKE '%canine%'
|
|---|
| 2574 | OR si.name ILIKE '%bravura%' OR si.name ILIKE '%andis%'
|
|---|
| 2575 | OR si.name ILIKE '%wahl%' OR si.name ILIKE '%furminator%' THEN 'Dog'
|
|---|
| 2576 | ELSE 'Dog & Cat'
|
|---|
| 2577 | END AS target_species,
|
|---|
| 2578 |
|
|---|
| 2579 | CASE
|
|---|
| 2580 | WHEN si.name ILIKE '%shampoo%' THEN 'Shampoo'
|
|---|
| 2581 | WHEN si.name ILIKE '%conditioner%' THEN 'Conditioner'
|
|---|
| 2582 | WHEN si.name ILIKE '%clipper%' THEN 'Clipper'
|
|---|
| 2583 | WHEN si.name ILIKE '%nail%' OR si.name ILIKE '%grinder%' THEN 'Nail care'
|
|---|
| 2584 | WHEN si.name ILIKE '%brush%' OR si.name ILIKE '%comb%' OR si.name ILIKE '%deShedding tool%' THEN 'Brush / comb'
|
|---|
| 2585 | WHEN si.name ILIKE '%dental%' OR si.name ILIKE '%oral%' OR si.name ILIKE '%toothbrush%' THEN 'Dental care'
|
|---|
| 2586 | WHEN si.name ILIKE '%mousse%' THEN 'Medicated mousse'
|
|---|
| 2587 | WHEN si.name ILIKE '%ear%' OR si.name ILIKE '%otic%' THEN 'Ear care'
|
|---|
| 2588 | WHEN si.name ILIKE '%wipe%' THEN 'Wipes'
|
|---|
| 2589 | WHEN si.name ILIKE '%water additive%' THEN 'Dental water additive'
|
|---|
| 2590 | ELSE 'General grooming'
|
|---|
| 2591 | END AS product_type,
|
|---|
| 2592 |
|
|---|
| 2593 | CASE
|
|---|
| 2594 | WHEN si.name ILIKE '%500ml%' THEN '500'
|
|---|
| 2595 | WHEN si.name ILIKE '%250ml%' THEN '250'
|
|---|
| 2596 | WHEN si.name ILIKE '%236ml%' THEN '236'
|
|---|
| 2597 | WHEN si.name ILIKE '%16oz%' THEN '473'
|
|---|
| 2598 | WHEN si.name ILIKE '%10oz%' THEN '295'
|
|---|
| 2599 | WHEN si.name ILIKE '%150ml%' THEN '150'
|
|---|
| 2600 | ELSE NULL
|
|---|
| 2601 | END AS volume_ml,
|
|---|
| 2602 |
|
|---|
| 2603 | CASE
|
|---|
| 2604 | WHEN si.name ILIKE '%oatmeal%' THEN 'Colloidal oatmeal'
|
|---|
| 2605 | WHEN si.name ILIKE '%tea tree%' THEN 'Tea tree oil'
|
|---|
| 2606 | WHEN si.name ILIKE '%hypoallerg%' THEN 'Aloe vera'
|
|---|
| 2607 | WHEN si.name ILIKE '%enzymatic%' THEN 'Glucose oxidase'
|
|---|
| 2608 | WHEN si.name ILIKE '%antiseptic%' THEN 'Chlorhexidine'
|
|---|
| 2609 | WHEN si.name ILIKE '%flea%' THEN 'Pyrethrin'
|
|---|
| 2610 | ELSE 'Gentle cleansing agents'
|
|---|
| 2611 | END AS key_ingredient,
|
|---|
| 2612 |
|
|---|
| 2613 | CASE
|
|---|
| 2614 | WHEN si.name ILIKE '%fresh breath%' OR si.name ILIKE '%mint%' THEN 'Mint'
|
|---|
| 2615 | WHEN si.name ILIKE '%fragrance free%' OR si.name ILIKE '%unscent%' THEN 'Unscented'
|
|---|
| 2616 | WHEN si.name ILIKE '%oatmeal%' THEN 'Oatmeal'
|
|---|
| 2617 | ELSE 'Lightly scented'
|
|---|
| 2618 | END AS scent
|
|---|
| 2619 | ) v(target_species, product_type, volume_ml, key_ingredient, scent)
|
|---|
| 2620 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2621 | CROSS JOIN LATERAL (
|
|---|
| 2622 | SELECT CASE a.name
|
|---|
| 2623 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2624 | WHEN 'product_type' THEN v.product_type
|
|---|
| 2625 | WHEN 'volume_ml' THEN v.volume_ml
|
|---|
| 2626 | WHEN 'key_ingredient' THEN v.key_ingredient
|
|---|
| 2627 | WHEN 'scent' THEN v.scent
|
|---|
| 2628 | END AS val
|
|---|
| 2629 | ) final_val(val)
|
|---|
| 2630 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2631 |
|
|---|
| 2632 |
|
|---|
| 2633 | -- ----------------------------------------------------------------
|
|---|
| 2634 | -- Toys attribute values
|
|---|
| 2635 | -- ----------------------------------------------------------------
|
|---|
| 2636 |
|
|---|
| 2637 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2638 | SELECT final_val.val, a.id, si.id
|
|---|
| 2639 | FROM shop_item si
|
|---|
| 2640 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Toys'
|
|---|
| 2641 | CROSS JOIN LATERAL (
|
|---|
| 2642 | SELECT
|
|---|
| 2643 | CASE
|
|---|
| 2644 | WHEN si.name ILIKE '%dog%' OR si.name ILIKE '%kong%' AND si.name NOT ILIKE '%cat%'
|
|---|
| 2645 | OR si.name ILIKE '%chuckit%' OR si.name ILIKE '%benebone%'
|
|---|
| 2646 | OR si.name ILIKE '%iFetch%' OR si.name ILIKE '%zippy%'
|
|---|
| 2647 | OR si.name ILIKE '%tug-a-jug%' THEN 'Dog'
|
|---|
| 2648 | WHEN si.name ILIKE '%cat%' OR si.name ILIKE '%da bird%' OR si.name ILIKE '%smartykat%'
|
|---|
| 2649 | OR si.name ILIKE '%petfusion%' OR si.name ILIKE '%catnip%'
|
|---|
| 2650 | OR si.name ILIKE '%catit%' OR si.name ILIKE '%jackson galaxy%' THEN 'Cat'
|
|---|
| 2651 | WHEN si.name ILIKE '%parrot%' OR si.name ILIKE '%bird%' OR si.name ILIKE '%perch%'
|
|---|
| 2652 | OR si.name ILIKE '%ladder%' OR si.name ILIKE '%penn-plax%' AND si.name ILIKE '%mirror%' THEN 'Bird'
|
|---|
| 2653 | WHEN si.name ILIKE '%hamster%' OR si.name ILIKE '%wheel%' OR si.name ILIKE '%exercise ball%'
|
|---|
| 2654 | OR si.name ILIKE '%tunnel%' OR si.name ILIKE '%kaytee%' AND si.name NOT ILIKE '%dog%' THEN 'Small Mammal'
|
|---|
| 2655 | WHEN si.name ILIKE '%skull%' OR si.name ILIKE '%betta%' OR si.name ILIKE '%aquarium%' THEN 'Fish'
|
|---|
| 2656 | ELSE 'Multi-species'
|
|---|
| 2657 | END AS target_species,
|
|---|
| 2658 |
|
|---|
| 2659 | CASE
|
|---|
| 2660 | WHEN si.name ILIKE '%small%' OR si.name ILIKE '% s ' THEN 'Small'
|
|---|
| 2661 | WHEN si.name ILIKE '%large%' OR si.name ILIKE '% l ' THEN 'Large'
|
|---|
| 2662 | WHEN si.name ILIKE '%medium%' THEN 'Medium'
|
|---|
| 2663 | ELSE 'Standard'
|
|---|
| 2664 | END AS size,
|
|---|
| 2665 |
|
|---|
| 2666 | CASE
|
|---|
| 2667 | WHEN si.name ILIKE '%rubber%' OR si.name ILIKE '%kong%' OR si.name ILIKE '%extreme%' THEN 'Natural rubber'
|
|---|
| 2668 | WHEN si.name ILIKE '%plush%' THEN 'Plush fabric'
|
|---|
| 2669 | WHEN si.name ILIKE '%wood%' OR si.name ILIKE '%wooden%' OR si.name ILIKE '%ladder%' THEN 'Wood'
|
|---|
| 2670 | WHEN si.name ILIKE '%plastic%' THEN 'ABS plastic'
|
|---|
| 2671 | WHEN si.name ILIKE '%feather%' THEN 'Feather & wire'
|
|---|
| 2672 | ELSE 'Mixed materials'
|
|---|
| 2673 | END AS material,
|
|---|
| 2674 |
|
|---|
| 2675 | CASE
|
|---|
| 2676 | WHEN si.name ILIKE '%interactive%' OR si.name ILIKE '%electronic%'
|
|---|
| 2677 | OR si.name ILIKE '%launcher%' OR si.name ILIKE '%ambush%'
|
|---|
| 2678 | OR si.name ILIKE '%wobbler%' OR si.name ILIKE '%smartykat%'
|
|---|
| 2679 | OR si.name ILIKE '%senses%' OR si.name ILIKE '%tug-a-jug%' THEN 'true'
|
|---|
| 2680 | ELSE 'false'
|
|---|
| 2681 | END AS interactive,
|
|---|
| 2682 |
|
|---|
| 2683 | CASE
|
|---|
| 2684 | WHEN si.name ILIKE '%dental%' OR si.name ILIKE '%chew%' OR si.name ILIKE '%benebone%'
|
|---|
| 2685 | OR si.name ILIKE '%nylabone%' THEN 'Chewing & dental'
|
|---|
| 2686 | WHEN si.name ILIKE '%fetch%' OR si.name ILIKE '%ball%' OR si.name ILIKE '%launcher%' THEN 'Fetch & chase'
|
|---|
| 2687 | WHEN si.name ILIKE '%puzzle%' OR si.name ILIKE '%hide%' OR si.name ILIKE '%wobbler%'
|
|---|
| 2688 | OR si.name ILIKE '%tug-a-jug%' OR si.name ILIKE '%food tree%' THEN 'Mental enrichment'
|
|---|
| 2689 | WHEN si.name ILIKE '%wheel%' OR si.name ILIKE '%exercise%' OR si.name ILIKE '%tunnel%' THEN 'Exercise'
|
|---|
| 2690 | WHEN si.name ILIKE '%catnip%' OR si.name ILIKE '%wand%' THEN 'Stimulation & hunting'
|
|---|
| 2691 | WHEN si.name ILIKE '%plush%' OR si.name ILIKE '%squirrel%' OR si.name ILIKE '%squeaky%' THEN 'Comfort & play'
|
|---|
| 2692 | ELSE 'General play'
|
|---|
| 2693 | END AS primary_activity
|
|---|
| 2694 | ) v(target_species, size, material, interactive, primary_activity)
|
|---|
| 2695 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2696 | CROSS JOIN LATERAL (
|
|---|
| 2697 | SELECT CASE a.name
|
|---|
| 2698 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2699 | WHEN 'size' THEN v.size
|
|---|
| 2700 | WHEN 'material' THEN v.material
|
|---|
| 2701 | WHEN 'interactive' THEN v.interactive
|
|---|
| 2702 | WHEN 'primary_activity' THEN v.primary_activity
|
|---|
| 2703 | END AS val
|
|---|
| 2704 | ) final_val(val)
|
|---|
| 2705 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2706 |
|
|---|
| 2707 |
|
|---|
| 2708 | -- ----------------------------------------------------------------
|
|---|
| 2709 | -- Clothing attribute values
|
|---|
| 2710 | -- ----------------------------------------------------------------
|
|---|
| 2711 |
|
|---|
| 2712 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2713 | SELECT final_val.val, a.id, si.id
|
|---|
| 2714 | FROM shop_item si
|
|---|
| 2715 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Clothing'
|
|---|
| 2716 | CROSS JOIN LATERAL (
|
|---|
| 2717 | SELECT
|
|---|
| 2718 | CASE
|
|---|
| 2719 | WHEN si.name ILIKE '%cat%' OR si.name ILIKE '%surgi%' THEN 'Cat / Small Dog'
|
|---|
| 2720 | ELSE 'Dog'
|
|---|
| 2721 | END AS target_species,
|
|---|
| 2722 |
|
|---|
| 2723 | CASE
|
|---|
| 2724 | WHEN si.name ILIKE '% xs%' OR si.name ILIKE '%xsmall%' OR si.name ILIKE '%extra small%' THEN 'XS'
|
|---|
| 2725 | WHEN si.name ILIKE '% s %' OR si.name ILIKE '% s/' OR si.name ILIKE '%small%' THEN 'S'
|
|---|
| 2726 | WHEN si.name ILIKE '% m %' OR si.name ILIKE '%medium%' THEN 'M'
|
|---|
| 2727 | WHEN si.name ILIKE '% l %' OR si.name ILIKE '%large%' THEN 'L'
|
|---|
| 2728 | WHEN si.name ILIKE '% xl%' OR si.name ILIKE '%xlarge%' OR si.name ILIKE '%extra large%' THEN 'XL'
|
|---|
| 2729 | ELSE 'Assorted'
|
|---|
| 2730 | END AS size,
|
|---|
| 2731 |
|
|---|
| 2732 | CASE
|
|---|
| 2733 | WHEN si.name ILIKE '%fleece%' THEN 'Fleece'
|
|---|
| 2734 | WHEN si.name ILIKE '%rubber%' THEN 'Natural rubber'
|
|---|
| 2735 | WHEN si.name ILIKE '%waterproof%' THEN 'Waterproof nylon'
|
|---|
| 2736 | WHEN si.name ILIKE '%puffer%' THEN 'Puffer nylon'
|
|---|
| 2737 | WHEN si.name ILIKE '%parka%' THEN 'Insulated nylon'
|
|---|
| 2738 | WHEN si.name ILIKE '%recovery%' OR si.name ILIKE '%surgi%' OR si.name ILIKE '%snuggly%' THEN 'Stretch cotton blend'
|
|---|
| 2739 | ELSE 'Polyester blend'
|
|---|
| 2740 | END AS material,
|
|---|
| 2741 |
|
|---|
| 2742 | CASE
|
|---|
| 2743 | WHEN si.name ILIKE '%black%' THEN 'Black'
|
|---|
| 2744 | WHEN si.name ILIKE '%blue%' THEN 'Blue'
|
|---|
| 2745 | WHEN si.name ILIKE '%red%' THEN 'Red'
|
|---|
| 2746 | WHEN si.name ILIKE '%pink%' THEN 'Pink'
|
|---|
| 2747 | ELSE 'Assorted'
|
|---|
| 2748 | END AS colour,
|
|---|
| 2749 |
|
|---|
| 2750 | CASE
|
|---|
| 2751 | WHEN si.name ILIKE '%hat%' THEN 'Hat'
|
|---|
| 2752 | WHEN si.name ILIKE '%jacket%' OR si.name ILIKE '%parka%'
|
|---|
| 2753 | OR si.name ILIKE '%coat%' OR si.name ILIKE '%puffer%'
|
|---|
| 2754 | OR si.name ILIKE '%vest%' AND si.name NOT ILIKE '%recovery%' THEN 'Jacket / Coat'
|
|---|
| 2755 | WHEN si.name ILIKE '%boot%' THEN 'Boots'
|
|---|
| 2756 | WHEN si.name ILIKE '%recovery%' OR si.name ILIKE '%surgi%'
|
|---|
| 2757 | OR si.name ILIKE '%suit%' THEN 'Recovery suit'
|
|---|
| 2758 | ELSE 'Clothing'
|
|---|
| 2759 | END AS clothing_type,
|
|---|
| 2760 |
|
|---|
| 2761 | CASE
|
|---|
| 2762 | WHEN si.name ILIKE '%waterproof%' OR si.name ILIKE '%parka%'
|
|---|
| 2763 | OR si.name ILIKE '%nor''easter%' OR si.name ILIKE '%grip trex%'
|
|---|
| 2764 | OR si.name ILIKE '%muttluks%' THEN 'true'
|
|---|
| 2765 | ELSE 'false'
|
|---|
| 2766 | END AS waterproof
|
|---|
| 2767 | ) v(target_species, size, material, colour, clothing_type, waterproof)
|
|---|
| 2768 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2769 | CROSS JOIN LATERAL (
|
|---|
| 2770 | SELECT CASE a.name
|
|---|
| 2771 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2772 | WHEN 'size' THEN v.size
|
|---|
| 2773 | WHEN 'material' THEN v.material
|
|---|
| 2774 | WHEN 'colour' THEN v.colour
|
|---|
| 2775 | WHEN 'clothing_type' THEN v.clothing_type
|
|---|
| 2776 | WHEN 'waterproof' THEN v.waterproof
|
|---|
| 2777 | END AS val
|
|---|
| 2778 | ) final_val(val)
|
|---|
| 2779 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2780 |
|
|---|
| 2781 |
|
|---|
| 2782 | -- ----------------------------------------------------------------
|
|---|
| 2783 | -- Medicine attribute values (for the ~60 shop items in 'Medicine')
|
|---|
| 2784 | -- ----------------------------------------------------------------
|
|---|
| 2785 |
|
|---|
| 2786 | INSERT INTO shop_item_attribute_value (value, shop_item_attribute_id, shop_item_id)
|
|---|
| 2787 | SELECT final_val.val, a.id, si.id
|
|---|
| 2788 | FROM shop_item si
|
|---|
| 2789 | JOIN shop_item_category sic ON sic.id = si.shop_item_category_id AND sic.name = 'Medicine'
|
|---|
| 2790 | CROSS JOIN LATERAL (
|
|---|
| 2791 | SELECT
|
|---|
| 2792 | CASE
|
|---|
| 2793 | WHEN si.name ILIKE '%tablet%' THEN 'Tablet'
|
|---|
| 2794 | WHEN si.name ILIKE '%capsule%' THEN 'Capsule'
|
|---|
| 2795 | WHEN si.name ILIKE '%injection%'OR si.name ILIKE '%inj%' THEN 'Injection'
|
|---|
| 2796 | WHEN si.name ILIKE '%solution%' OR si.name ILIKE '%suspension%'
|
|---|
| 2797 | OR si.name ILIKE '%oral%' THEN 'Oral solution'
|
|---|
| 2798 | WHEN si.name ILIKE '%granule%' THEN 'Granules'
|
|---|
| 2799 | WHEN si.name ILIKE '%powder%' THEN 'Powder'
|
|---|
| 2800 | WHEN si.name ILIKE '%infusion%' THEN 'IV infusion'
|
|---|
| 2801 | WHEN si.name ILIKE '%flush%' THEN 'Sterile solution'
|
|---|
| 2802 | ELSE 'Tablet'
|
|---|
| 2803 | END AS dosage_form,
|
|---|
| 2804 |
|
|---|
| 2805 | -- extract strength from name (e.g. '250mg', '1.5mg/ml', '20%')
|
|---|
| 2806 | COALESCE(
|
|---|
| 2807 | (regexp_match(si.name,
|
|---|
| 2808 | '(\d+(?:\.\d+)?\s*(?:mg|mcg|g|%|IU)(?:/ml|/\d+ml)?)'))[1],
|
|---|
| 2809 | 'See label'
|
|---|
| 2810 | ) AS strength,
|
|---|
| 2811 |
|
|---|
| 2812 | CASE
|
|---|
| 2813 | WHEN si.name ILIKE '%10 pack%' OR si.name ILIKE '%10ct%' THEN '10'
|
|---|
| 2814 | WHEN si.name ILIKE '%28%' THEN '28'
|
|---|
| 2815 | WHEN si.name ILIKE '%30%' THEN '30'
|
|---|
| 2816 | WHEN si.name ILIKE '%60%' THEN '60'
|
|---|
| 2817 | WHEN si.name ILIKE '%100ml%' THEN '1' -- vials
|
|---|
| 2818 | WHEN si.name ILIKE '%10ml%' THEN '1'
|
|---|
| 2819 | ELSE '30'
|
|---|
| 2820 | END AS pack_size,
|
|---|
| 2821 |
|
|---|
| 2822 | 'false' AS prescription_only, -- all items in shop are OTC
|
|---|
| 2823 |
|
|---|
| 2824 | 'Dog & Cat' AS target_species
|
|---|
| 2825 | ) v(dosage_form, strength, pack_size, prescription_only, target_species)
|
|---|
| 2826 | JOIN shop_item_attribute a ON a.shop_item_category_id = sic.id
|
|---|
| 2827 | CROSS JOIN LATERAL (
|
|---|
| 2828 | SELECT CASE a.name
|
|---|
| 2829 | WHEN 'dosage_form' THEN v.dosage_form
|
|---|
| 2830 | WHEN 'strength' THEN v.strength
|
|---|
| 2831 | WHEN 'pack_size' THEN v.pack_size
|
|---|
| 2832 | WHEN 'prescription_only' THEN v.prescription_only
|
|---|
| 2833 | WHEN 'target_species' THEN v.target_species
|
|---|
| 2834 | END AS val
|
|---|
| 2835 | ) final_val(val)
|
|---|
| 2836 | WHERE final_val.val IS NOT NULL;
|
|---|
| 2837 |
|
|---|
| 2838 |
|
|---|
| 2839 | -- ============================================================
|
|---|
| 2840 | -- remaining treatments (consultation, operation)
|
|---|
| 2841 | -- + treatment_attribute and treatment_attribute_value
|
|---|
| 2842 | -- for all 4 types:
|
|---|
| 2843 | -- prescription, vaccination, consultation, operation
|
|---|
| 2844 | -- ============================================================
|
|---|
| 2845 |
|
|---|
| 2846 |
|
|---|
| 2847 | -- ============================================================
|
|---|
| 2848 | -- treatment — consultation
|
|---|
| 2849 | -- One per completed examination that doesn't already have
|
|---|
| 2850 | -- a consultation treatment.
|
|---|
| 2851 | -- We give roughly 60% of completed exams a consultation.
|
|---|
| 2852 | -- ============================================================
|
|---|
| 2853 |
|
|---|
| 2854 | INSERT INTO treatment (date_treatment, notes, treatment_type_id, examination_id)
|
|---|
| 2855 | SELECT
|
|---|
| 2856 | e.date_examination + (floor(random() * 3))::int AS date_treatment,
|
|---|
| 2857 |
|
|---|
| 2858 | notes_list.notes,
|
|---|
| 2859 |
|
|---|
| 2860 | (SELECT id FROM treatment_type WHERE name = 'consultation') AS treatment_type_id,
|
|---|
| 2861 |
|
|---|
| 2862 | e.id AS examination_id
|
|---|
| 2863 |
|
|---|
| 2864 | FROM examination e
|
|---|
| 2865 | CROSS JOIN LATERAL (
|
|---|
| 2866 | SELECT notes
|
|---|
| 2867 | FROM (VALUES
|
|---|
| 2868 | ('Owner counselled on diet and weight management.'),
|
|---|
| 2869 | ('Behavioural concerns discussed; referral considered.'),
|
|---|
| 2870 | ('Vaccination schedule reviewed with owner.'),
|
|---|
| 2871 | ('Pain management options explained to owner.'),
|
|---|
| 2872 | ('Discussed long-term management of chronic condition.'),
|
|---|
| 2873 | ('Follow-up plan agreed; owner given written summary.'),
|
|---|
| 2874 | ('Discussed surgical options and associated risks.'),
|
|---|
| 2875 | ('Dental hygiene advice provided; home care demonstrated.'),
|
|---|
| 2876 | ('Parasite prevention programme reviewed.'),
|
|---|
| 2877 | ('Nutritional counselling completed; diet change recommended.')
|
|---|
| 2878 | ) AS n(notes)
|
|---|
| 2879 | WHERE e.id IS NOT NULL
|
|---|
| 2880 | ORDER BY random()
|
|---|
| 2881 | LIMIT 1
|
|---|
| 2882 | ) notes_list
|
|---|
| 2883 | WHERE e.status = 'completed'
|
|---|
| 2884 | AND random() < 0.60
|
|---|
| 2885 | AND NOT EXISTS (
|
|---|
| 2886 | SELECT 1 FROM treatment t
|
|---|
| 2887 | JOIN treatment_type tt ON tt.id = t.treatment_type_id
|
|---|
| 2888 | WHERE t.examination_id = e.id AND tt.name = 'consultation'
|
|---|
| 2889 | );
|
|---|
| 2890 |
|
|---|
| 2891 |
|
|---|
| 2892 | -- ============================================================
|
|---|
| 2893 | -- treatment — operation
|
|---|
| 2894 | -- ~20% of completed exams get an operation treatment.
|
|---|
| 2895 | -- ============================================================
|
|---|
| 2896 |
|
|---|
| 2897 | INSERT INTO treatment (date_treatment, notes, treatment_type_id, examination_id)
|
|---|
| 2898 | SELECT
|
|---|
| 2899 | e.date_examination + (floor(random() * 2))::int AS date_treatment,
|
|---|
| 2900 |
|
|---|
| 2901 | notes_list.notes,
|
|---|
| 2902 |
|
|---|
| 2903 | (SELECT id FROM treatment_type WHERE name = 'operation') AS treatment_type_id,
|
|---|
| 2904 |
|
|---|
| 2905 | e.id AS examination_id
|
|---|
| 2906 |
|
|---|
| 2907 | FROM examination e
|
|---|
| 2908 | CROSS JOIN LATERAL (
|
|---|
| 2909 | SELECT notes
|
|---|
| 2910 | FROM (VALUES
|
|---|
| 2911 | ('Surgery performed without complications.'),
|
|---|
| 2912 | ('Procedure completed; patient recovering well.'),
|
|---|
| 2913 | ('Intraoperative findings documented; owner informed.'),
|
|---|
| 2914 | ('Operation successful; post-op care instructions given.'),
|
|---|
| 2915 | ('Surgical site closed; patient moved to recovery ward.'),
|
|---|
| 2916 | ('Procedure carried out under general anaesthesia.'),
|
|---|
| 2917 | ('Minor intraoperative bleeding managed; outcome satisfactory.'),
|
|---|
| 2918 | ('Patient stable post-operatively; monitoring ongoing.'),
|
|---|
| 2919 | ('Surgery completed; follow-up scheduled in 10 days.'),
|
|---|
| 2920 | ('Operative procedure completed; histopathology sample submitted.')
|
|---|
| 2921 | ) AS n(notes)
|
|---|
| 2922 | WHERE e.id IS NOT NULL
|
|---|
| 2923 | ORDER BY random()
|
|---|
| 2924 | LIMIT 1
|
|---|
| 2925 | ) notes_list
|
|---|
| 2926 | WHERE e.status = 'completed'
|
|---|
| 2927 | AND random() < 0.20
|
|---|
| 2928 | AND NOT EXISTS (
|
|---|
| 2929 | SELECT 1 FROM treatment t
|
|---|
| 2930 | JOIN treatment_type tt ON tt.id = t.treatment_type_id
|
|---|
| 2931 | WHERE t.examination_id = e.id AND tt.name = 'operation'
|
|---|
| 2932 | );
|
|---|
| 2933 |
|
|---|
| 2934 |
|
|---|
| 2935 | -- ============================================================
|
|---|
| 2936 | -- treatment_attribute
|
|---|
| 2937 | -- One attribute set per treatment_type.
|
|---|
| 2938 | -- ============================================================
|
|---|
| 2939 |
|
|---|
| 2940 | -- ---------- prescription ----------
|
|---|
| 2941 | INSERT INTO treatment_attribute (name, data_type, treatment_type_id)
|
|---|
| 2942 | SELECT attr, dtype,
|
|---|
| 2943 | (SELECT id FROM treatment_type WHERE name = 'prescription')
|
|---|
| 2944 | FROM (VALUES
|
|---|
| 2945 | ('medication_class', 'text'),
|
|---|
| 2946 | ('route', 'text'),
|
|---|
| 2947 | ('refills_allowed', 'integer'),
|
|---|
| 2948 | ('withdrawal_period', 'text')
|
|---|
| 2949 | ) AS t(attr, dtype);
|
|---|
| 2950 |
|
|---|
| 2951 | -- ---------- vaccination ----------
|
|---|
| 2952 | INSERT INTO treatment_attribute (name, data_type, treatment_type_id)
|
|---|
| 2953 | SELECT attr, dtype,
|
|---|
| 2954 | (SELECT id FROM treatment_type WHERE name = 'vaccination')
|
|---|
| 2955 | FROM (VALUES
|
|---|
| 2956 | ('vaccine_name', 'text'),
|
|---|
| 2957 | ('manufacturer', 'text'),
|
|---|
| 2958 | ('batch_number', 'text'),
|
|---|
| 2959 | ('num_doses', 'integer'),
|
|---|
| 2960 | ('dose_number', 'integer'),
|
|---|
| 2961 | ('route', 'text'),
|
|---|
| 2962 | ('site', 'text'),
|
|---|
| 2963 | ('date_next', 'date'),
|
|---|
| 2964 | ('adverse_reaction', 'boolean')
|
|---|
| 2965 | ) AS t(attr, dtype);
|
|---|
| 2966 |
|
|---|
| 2967 | -- ---------- consultation ----------
|
|---|
| 2968 | INSERT INTO treatment_attribute (name, data_type, treatment_type_id)
|
|---|
| 2969 | SELECT attr, dtype,
|
|---|
| 2970 | (SELECT id FROM treatment_type WHERE name = 'consultation')
|
|---|
| 2971 | FROM (VALUES
|
|---|
| 2972 | ('topic', 'text'),
|
|---|
| 2973 | ('description', 'text'),
|
|---|
| 2974 | ('referral', 'boolean'),
|
|---|
| 2975 | ('referral_to', 'text'),
|
|---|
| 2976 | ('follow_up_days', 'integer'),
|
|---|
| 2977 | ('owner_present', 'boolean')
|
|---|
| 2978 | ) AS t(attr, dtype);
|
|---|
| 2979 |
|
|---|
| 2980 | -- ---------- operation ----------
|
|---|
| 2981 | INSERT INTO treatment_attribute (name, data_type, treatment_type_id)
|
|---|
| 2982 | SELECT attr, dtype,
|
|---|
| 2983 | (SELECT id FROM treatment_type WHERE name = 'operation')
|
|---|
| 2984 | FROM (VALUES
|
|---|
| 2985 | ('operation_type', 'text'),
|
|---|
| 2986 | ('status', 'text'),
|
|---|
| 2987 | ('anesthesia', 'text'),
|
|---|
| 2988 | ('duration_minutes', 'integer'),
|
|---|
| 2989 | ('date_checkup', 'date'),
|
|---|
| 2990 | ('surgeon', 'text'),
|
|---|
| 2991 | ('complications', 'boolean')
|
|---|
| 2992 | ) AS t(attr, dtype);
|
|---|
| 2993 |
|
|---|
| 2994 |
|
|---|
| 2995 | -- ============================================================
|
|---|
| 2996 | -- treatment_attribute_value
|
|---|
| 2997 | -- One value per (treatment x attribute) for every treatment.
|
|---|
| 2998 | -- ============================================================
|
|---|
| 2999 |
|
|---|
| 3000 | -- ----------------------------------------------------------------
|
|---|
| 3001 | -- PRESCRIPTION treatment attribute values
|
|---|
| 3002 | -- ----------------------------------------------------------------
|
|---|
| 3003 |
|
|---|
| 3004 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 3005 | SELECT
|
|---|
| 3006 | final_val.val,
|
|---|
| 3007 | NULL,
|
|---|
| 3008 | a.id,
|
|---|
| 3009 | t.id
|
|---|
| 3010 | FROM treatment t
|
|---|
| 3011 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'prescription'
|
|---|
| 3012 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 3013 | CROSS JOIN LATERAL (
|
|---|
| 3014 | -- generate all 6 attribute values in one lateral
|
|---|
| 3015 | SELECT
|
|---|
| 3016 | (ARRAY['Antibiotic','NSAID','Corticosteroid','Antiparasitic',
|
|---|
| 3017 | 'Antifungal','Analgesic','Anticonvulsant','Cardiac',
|
|---|
| 3018 | 'Gastrointestinal','Immunosuppressant'])
|
|---|
| 3019 | [1 + (abs(hashtext(t.id::text || 'cls')) % 10)] AS medication_class,
|
|---|
| 3020 |
|
|---|
| 3021 | (ARRAY['Oral','Subcutaneous injection','Intramuscular injection',
|
|---|
| 3022 | 'Topical','Intravenous','Ophthalmic'])
|
|---|
| 3023 | [1 + (abs(hashtext(t.id::text || 'rte')) % 6)] AS route,
|
|---|
| 3024 |
|
|---|
| 3025 | (abs(hashtext(t.id::text || 'ref')) % 3)::text AS refills_allowed,
|
|---|
| 3026 |
|
|---|
| 3027 | CASE (abs(hashtext(t.id::text || 'wth')) % 3)
|
|---|
| 3028 | WHEN 0 THEN 'None'
|
|---|
| 3029 | WHEN 1 THEN '24 hours'
|
|---|
| 3030 | ELSE '48 hours'
|
|---|
| 3031 | END AS withdrawal_period
|
|---|
| 3032 | ) v
|
|---|
| 3033 | CROSS JOIN LATERAL (
|
|---|
| 3034 | SELECT CASE a.name
|
|---|
| 3035 | WHEN 'medication_class' THEN v.medication_class
|
|---|
| 3036 | WHEN 'route' THEN v.route
|
|---|
| 3037 | WHEN 'refills_allowed' THEN v.refills_allowed
|
|---|
| 3038 | WHEN 'withdrawal_period' THEN v.withdrawal_period
|
|---|
| 3039 | END AS val
|
|---|
| 3040 | ) final_val
|
|---|
| 3041 | WHERE final_val.val IS NOT NULL;
|
|---|
| 3042 |
|
|---|
| 3043 |
|
|---|
| 3044 | -- ----------------------------------------------------------------
|
|---|
| 3045 | -- VACCINATION treatment attribute values
|
|---|
| 3046 | -- ----------------------------------------------------------------
|
|---|
| 3047 |
|
|---|
| 3048 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 3049 | SELECT
|
|---|
| 3050 | final_val.val,
|
|---|
| 3051 | NULL,
|
|---|
| 3052 | a.id,
|
|---|
| 3053 | t.id
|
|---|
| 3054 | FROM treatment t
|
|---|
| 3055 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'vaccination'
|
|---|
| 3056 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 3057 | CROSS JOIN LATERAL (
|
|---|
| 3058 | SELECT
|
|---|
| 3059 | (ARRAY[
|
|---|
| 3060 | 'Nobivac DHPPi',
|
|---|
| 3061 | 'Nobivac Rabies',
|
|---|
| 3062 | 'Feligen CRP',
|
|---|
| 3063 | 'Purevax RCPCh',
|
|---|
| 3064 | 'Versican Plus DHPPi/L4',
|
|---|
| 3065 | 'Canigen L4',
|
|---|
| 3066 | 'Nobivac Lepto 4',
|
|---|
| 3067 | 'Eurican Herpes 205',
|
|---|
| 3068 | 'Felocell CVR',
|
|---|
| 3069 | 'Quantum Cat 7'
|
|---|
| 3070 | ])[1 + (abs(hashtext(t.id::text || 'vac')) % 10)] AS vaccine_name,
|
|---|
| 3071 |
|
|---|
| 3072 | (ARRAY['Zoetis','MSD Animal Health','Boehringer Ingelheim',
|
|---|
| 3073 | 'Virbac','Elanco'])
|
|---|
| 3074 | [1 + (abs(hashtext(t.id::text || 'mfr')) % 5)] AS manufacturer,
|
|---|
| 3075 |
|
|---|
| 3076 | 'BN-' || lpad((abs(hashtext(t.id::text || 'bn')) % 900000 + 100000)::text, 6, '0')
|
|---|
| 3077 | AS batch_number,
|
|---|
| 3078 |
|
|---|
| 3079 | CASE (abs(hashtext(t.id::text || 'nd')) % 3)
|
|---|
| 3080 | WHEN 0 THEN '1'
|
|---|
| 3081 | WHEN 1 THEN '2'
|
|---|
| 3082 | ELSE '3'
|
|---|
| 3083 | END AS num_doses,
|
|---|
| 3084 |
|
|---|
| 3085 | -- dose number in series (1 or 2)
|
|---|
| 3086 | CASE (abs(hashtext(t.id::text || 'dn')) % 2)
|
|---|
| 3087 | WHEN 0 THEN '1'
|
|---|
| 3088 | ELSE '2'
|
|---|
| 3089 | END AS dose_number,
|
|---|
| 3090 |
|
|---|
| 3091 | (ARRAY['Subcutaneous','Intramuscular','Intranasal'])
|
|---|
| 3092 | [1 + (abs(hashtext(t.id::text || 'rt2')) % 3)] AS route,
|
|---|
| 3093 |
|
|---|
| 3094 | (ARRAY['Right scruff','Left scruff','Right hindlimb','Left hindlimb'])
|
|---|
| 3095 | [1 + (abs(hashtext(t.id::text || 'ste')) % 4)] AS site,
|
|---|
| 3096 |
|
|---|
| 3097 | -- date_next: 1 year after treatment date
|
|---|
| 3098 | (t.date_treatment + interval '1 year')::date::text AS date_next,
|
|---|
| 3099 |
|
|---|
| 3100 | -- adverse reaction: 3% chance
|
|---|
| 3101 | CASE WHEN (abs(hashtext(t.id::text || 'adv')) % 100) < 3
|
|---|
| 3102 | THEN 'true' ELSE 'false'
|
|---|
| 3103 | END AS adverse_reaction
|
|---|
| 3104 | ) v
|
|---|
| 3105 | CROSS JOIN LATERAL (
|
|---|
| 3106 | SELECT CASE a.name
|
|---|
| 3107 | WHEN 'vaccine_name' THEN v.vaccine_name
|
|---|
| 3108 | WHEN 'manufacturer' THEN v.manufacturer
|
|---|
| 3109 | WHEN 'batch_number' THEN v.batch_number
|
|---|
| 3110 | WHEN 'num_doses' THEN v.num_doses
|
|---|
| 3111 | WHEN 'dose_number' THEN v.dose_number
|
|---|
| 3112 | WHEN 'route' THEN v.route
|
|---|
| 3113 | WHEN 'site' THEN v.site
|
|---|
| 3114 | WHEN 'date_next' THEN v.date_next
|
|---|
| 3115 | WHEN 'adverse_reaction' THEN v.adverse_reaction
|
|---|
| 3116 | END AS val
|
|---|
| 3117 | ) final_val
|
|---|
| 3118 | WHERE final_val.val IS NOT NULL;
|
|---|
| 3119 |
|
|---|
| 3120 |
|
|---|
| 3121 | -- ----------------------------------------------------------------
|
|---|
| 3122 | -- CONSULTATION treatment attribute values
|
|---|
| 3123 | -- ----------------------------------------------------------------
|
|---|
| 3124 |
|
|---|
| 3125 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 3126 | SELECT
|
|---|
| 3127 | final_val.val,
|
|---|
| 3128 | NULL,
|
|---|
| 3129 | a.id,
|
|---|
| 3130 | t.id
|
|---|
| 3131 | FROM treatment t
|
|---|
| 3132 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'consultation'
|
|---|
| 3133 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 3134 | CROSS JOIN LATERAL (
|
|---|
| 3135 | SELECT
|
|---|
| 3136 | (ARRAY[
|
|---|
| 3137 | 'Nutrition and weight management',
|
|---|
| 3138 | 'Behavioural assessment',
|
|---|
| 3139 | 'Chronic disease management',
|
|---|
| 3140 | 'Pre-surgical counselling',
|
|---|
| 3141 | 'Post-operative care planning',
|
|---|
| 3142 | 'Dental hygiene advice',
|
|---|
| 3143 | 'Parasite prevention review',
|
|---|
| 3144 | 'Vaccination schedule planning',
|
|---|
| 3145 | 'End-of-life care discussion',
|
|---|
| 3146 | 'Second opinion review'
|
|---|
| 3147 | ])[1 + (abs(hashtext(t.id::text || 'top')) % 10)] AS topic,
|
|---|
| 3148 |
|
|---|
| 3149 | (ARRAY[
|
|---|
| 3150 | 'Owner presented concerns regarding the pet''s appetite and energy levels. A full dietary review was completed and a lower-calorie prescription diet was recommended. Owner was shown how to measure portions correctly and advised to recheck in 4 weeks.',
|
|---|
| 3151 | 'Behavioural history taken in detail. Pet displays anxiety-related signs including excessive grooming and vocalization. Environmental enrichment strategies discussed and a referral to a veterinary behaviourist was considered.',
|
|---|
| 3152 | 'Long-term management plan for the pet''s diagnosed chronic kidney disease was reviewed. Blood results interpreted and ACE inhibitor dosage adjusted. Owner counselled on signs of deterioration and instructed to return if vomiting or lethargy develops.',
|
|---|
| 3153 | 'Pre-surgical consultation completed for elective spay procedure. Risks and benefits of anaesthesia explained. Pre-operative blood panel ordered. Owner provided written consent and fasting instructions.',
|
|---|
| 3154 | 'Post-operative wound checked and healing progress assessed. Owner demonstrated correct application of topical antiseptic and Elizabeth collar use. Suture removal booked for 10 days post-op.',
|
|---|
| 3155 | 'Dental examination findings discussed with owner. Stage 2 periodontal disease identified. Professional scale and polish recommended. Home brushing technique demonstrated using enzymatic toothpaste.',
|
|---|
| 3156 | 'Current parasite prevention programme assessed. Owner using an incomplete product that does not cover lungworm. Updated protocol prescribed combining monthly spot-on and quarterly wormer. Environmental hygiene advice given.',
|
|---|
| 3157 | 'Full vaccination history reviewed. Pet was overdue for core and leptospirosis boosters. Schedule re-established; primary course restarted where titre testing was not available. Owner reminded of annual requirement.',
|
|---|
| 3158 | 'Compassionate discussion held with owner regarding quality of life for their senior pet with advanced neoplasia. Palliative care options including pain management and hospice-style support outlined. Owner given time to consider options.',
|
|---|
| 3159 | 'Second opinion consultation for recurrent skin condition. Previous treatment history reviewed. Differential diagnoses reconsidered; skin biopsy recommended to rule out immune-mediated disease.'
|
|---|
| 3160 | ])[1 + (abs(hashtext(t.id::text || 'dsc')) % 10)] AS description,
|
|---|
| 3161 |
|
|---|
| 3162 | -- referral: 15% chance
|
|---|
| 3163 | CASE WHEN (abs(hashtext(t.id::text || 'ref')) % 100) < 15
|
|---|
| 3164 | THEN 'true' ELSE 'false'
|
|---|
| 3165 | END AS referral,
|
|---|
| 3166 |
|
|---|
| 3167 | CASE WHEN (abs(hashtext(t.id::text || 'ref')) % 100) < 15
|
|---|
| 3168 | THEN (ARRAY[
|
|---|
| 3169 | 'Veterinary Dermatologist',
|
|---|
| 3170 | 'Veterinary Cardiologist',
|
|---|
| 3171 | 'Veterinary Behaviourist',
|
|---|
| 3172 | 'Veterinary Oncologist',
|
|---|
| 3173 | 'Veterinary Ophthalmologist',
|
|---|
| 3174 | 'Veterinary Neurologist'
|
|---|
| 3175 | ])[1 + (abs(hashtext(t.id::text || 'rto')) % 6)]
|
|---|
| 3176 | ELSE NULL
|
|---|
| 3177 | END AS referral_to,
|
|---|
| 3178 |
|
|---|
| 3179 | -- follow-up in 7, 14, 21 or 30 days
|
|---|
| 3180 | (ARRAY['7','14','21','30'])
|
|---|
| 3181 | [1 + (abs(hashtext(t.id::text || 'fup')) % 4)] AS follow_up_days,
|
|---|
| 3182 |
|
|---|
| 3183 | -- owner present: almost always true
|
|---|
| 3184 | CASE WHEN (abs(hashtext(t.id::text || 'own')) % 10) < 9
|
|---|
| 3185 | THEN 'true' ELSE 'false'
|
|---|
| 3186 | END AS owner_present
|
|---|
| 3187 | ) v
|
|---|
| 3188 | CROSS JOIN LATERAL (
|
|---|
| 3189 | SELECT CASE a.name
|
|---|
| 3190 | WHEN 'topic' THEN v.topic
|
|---|
| 3191 | WHEN 'description' THEN v.description
|
|---|
| 3192 | WHEN 'referral' THEN v.referral
|
|---|
| 3193 | WHEN 'referral_to' THEN v.referral_to
|
|---|
| 3194 | WHEN 'follow_up_days' THEN v.follow_up_days
|
|---|
| 3195 | WHEN 'owner_present' THEN v.owner_present
|
|---|
| 3196 | END AS val
|
|---|
| 3197 | ) final_val
|
|---|
| 3198 | WHERE final_val.val IS NOT NULL;
|
|---|
| 3199 |
|
|---|
| 3200 |
|
|---|
| 3201 | -- ----------------------------------------------------------------
|
|---|
| 3202 | -- OPERATION treatment attribute values
|
|---|
| 3203 | -- ----------------------------------------------------------------
|
|---|
| 3204 |
|
|---|
| 3205 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 3206 | SELECT
|
|---|
| 3207 | final_val.val,
|
|---|
| 3208 | NULL,
|
|---|
| 3209 | a.id,
|
|---|
| 3210 | t.id
|
|---|
| 3211 | FROM treatment t
|
|---|
| 3212 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'operation'
|
|---|
| 3213 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 3214 | CROSS JOIN LATERAL (
|
|---|
| 3215 | SELECT
|
|---|
| 3216 | (ARRAY[
|
|---|
| 3217 | 'Ovariohysterectomy (spay)',
|
|---|
| 3218 | 'Orchiectomy (neuter)',
|
|---|
| 3219 | 'Mass / tumour excision',
|
|---|
| 3220 | 'Fracture repair (ORIF)',
|
|---|
| 3221 | 'Intestinal foreign body removal',
|
|---|
| 3222 | 'Cystotomy (bladder stone removal)',
|
|---|
| 3223 | 'Gastropexy',
|
|---|
| 3224 | 'Enucleation',
|
|---|
| 3225 | 'Amputation',
|
|---|
| 3226 | 'Caesarean section',
|
|---|
| 3227 | 'Exploratory laparotomy',
|
|---|
| 3228 | 'Cruciate ligament repair (TPLO)',
|
|---|
| 3229 | 'Dental extraction',
|
|---|
| 3230 | 'Wound debridement and closure',
|
|---|
| 3231 | 'Thoracostomy tube placement'
|
|---|
| 3232 | ])[1 + (abs(hashtext(t.id::text || 'opt')) % 15)] AS operation_type,
|
|---|
| 3233 |
|
|---|
| 3234 | -- status: mostly successful
|
|---|
| 3235 | (ARRAY['Successful','Successful','Successful','Successful',
|
|---|
| 3236 | 'Complicated','Unsuccessful'])
|
|---|
| 3237 | [1 + (abs(hashtext(t.id::text || 'sts')) % 6)] AS status,
|
|---|
| 3238 |
|
|---|
| 3239 | (ARRAY[
|
|---|
| 3240 | 'Propofol induction / Isoflurane maintenance',
|
|---|
| 3241 | 'Alfaxalone induction / Isoflurane maintenance',
|
|---|
| 3242 | 'Ketamine-Midazolam / Isoflurane maintenance',
|
|---|
| 3243 | 'Propofol TIVA',
|
|---|
| 3244 | 'Medetomidine-Butorphanol sedation (minor procedure)'
|
|---|
| 3245 | ])[1 + (abs(hashtext(t.id::text || 'ans')) % 5)] AS anesthesia,
|
|---|
| 3246 |
|
|---|
| 3247 | -- duration: 15–180 minutes
|
|---|
| 3248 | (15 + (abs(hashtext(t.id::text || 'dur')) % 166))::text AS duration_minutes,
|
|---|
| 3249 |
|
|---|
| 3250 | -- checkup date: 7–14 days after treatment
|
|---|
| 3251 | (t.date_treatment + (7 + abs(hashtext(t.id::text || 'chk')) % 8))::text
|
|---|
| 3252 | AS date_checkup,
|
|---|
| 3253 |
|
|---|
| 3254 | -- surgeon: reference one of the vets by name (lookup from employee)
|
|---|
| 3255 | (
|
|---|
| 3256 | SELECT e.first_name || ' ' || e.last_name
|
|---|
| 3257 | FROM employee e
|
|---|
| 3258 | WHERE e.role_id = 2
|
|---|
| 3259 | ORDER BY abs(hashtext(t.id::text || 'srg' || e.id::text))
|
|---|
| 3260 | LIMIT 1
|
|---|
| 3261 | ) AS surgeon,
|
|---|
| 3262 |
|
|---|
| 3263 | -- complications: ~12%
|
|---|
| 3264 | CASE WHEN (abs(hashtext(t.id::text || 'cmp')) % 100) < 12
|
|---|
| 3265 | THEN 'true' ELSE 'false'
|
|---|
| 3266 | END AS complications
|
|---|
| 3267 | ) v
|
|---|
| 3268 | CROSS JOIN LATERAL (
|
|---|
| 3269 | SELECT CASE a.name
|
|---|
| 3270 | WHEN 'operation_type' THEN v.operation_type
|
|---|
| 3271 | WHEN 'status' THEN v.status
|
|---|
| 3272 | WHEN 'anesthesia' THEN v.anesthesia
|
|---|
| 3273 | WHEN 'duration_minutes' THEN v.duration_minutes
|
|---|
| 3274 | WHEN 'date_checkup' THEN v.date_checkup
|
|---|
| 3275 | WHEN 'surgeon' THEN v.surgeon
|
|---|
| 3276 | WHEN 'complications' THEN v.complications
|
|---|
| 3277 | END AS val
|
|---|
| 3278 | ) final_val
|
|---|
| 3279 | WHERE final_val.val IS NOT NULL;
|
|---|
| 3280 |
|
|---|
| 3281 |
|
|---|
| 3282 |
|
|---|
| 3283 | -- temp table for imported medicines
|
|---|
| 3284 | create table temp_med1
|
|---|
| 3285 | (
|
|---|
| 3286 | id bigserial primary key,
|
|---|
| 3287 | name varchar
|
|---|
| 3288 | );
|
|---|
| 3289 |
|
|---|
| 3290 | -- drop table temp_med1 cascade;
|
|---|
| 3291 |
|
|---|
| 3292 | COPY temp_med1 (name) FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/medicine.csv' DELIMITER ',' CSV HEADER;
|
|---|
| 3293 | UPDATE temp_med1
|
|---|
| 3294 | SET name = TRIM(name);
|
|---|
| 3295 |
|
|---|
| 3296 |
|
|---|
| 3297 | -- ============================================================
|
|---|
| 3298 | -- STEP 3a — Insert medicines from temp_med1
|
|---|
| 3299 | -- Assign a plausible manufacturer and description based on
|
|---|
| 3300 | -- the medicine name. shop_item_id is NULL (prescription-only
|
|---|
| 3301 | -- or clinic-use; they are not in the shop).
|
|---|
| 3302 | -- ============================================================
|
|---|
| 3303 |
|
|---|
| 3304 | INSERT INTO medicine (name, manufacturer, description, shop_item_id)
|
|---|
| 3305 | SELECT
|
|---|
| 3306 | t.name,
|
|---|
| 3307 |
|
|---|
| 3308 | -- deterministic but varied manufacturer
|
|---|
| 3309 | (ARRAY[
|
|---|
| 3310 | 'Zoetis Inc.',
|
|---|
| 3311 | 'Boehringer Ingelheim',
|
|---|
| 3312 | 'Elanco Animal Health',
|
|---|
| 3313 | 'Virbac Animal Health',
|
|---|
| 3314 | 'Dechra Veterinary',
|
|---|
| 3315 | 'Norbrook Laboratories',
|
|---|
| 3316 | 'Vetoquinol',
|
|---|
| 3317 | 'Bayer Animal Health',
|
|---|
| 3318 | 'MSD Animal Health',
|
|---|
| 3319 | 'Pfizer Animal Health',
|
|---|
| 3320 | 'Jurox Animal Health',
|
|---|
| 3321 | 'Intervet-Schering Plough',
|
|---|
| 3322 | 'Novartis Animal Health',
|
|---|
| 3323 | 'Merial',
|
|---|
| 3324 | 'Orion Pharma'
|
|---|
| 3325 | ])[1 + (abs(hashtext(t.name || 'mfr')) % 15)] AS manufacturer,
|
|---|
| 3326 |
|
|---|
| 3327 | -- plausible description derived from name keywords
|
|---|
| 3328 | CASE
|
|---|
| 3329 | WHEN t.name ILIKE '%amoxicillin%' OR t.name ILIKE '%ampicillin%'
|
|---|
| 3330 | OR t.name ILIKE '%penicillin%'
|
|---|
| 3331 | THEN 'Penicillin-class antibiotic for bacterial infections in companion animals'
|
|---|
| 3332 |
|
|---|
| 3333 | WHEN t.name ILIKE '%cefalex%' OR t.name ILIKE '%cephalex%'
|
|---|
| 3334 | OR t.name ILIKE '%cefovecin%' OR t.name ILIKE '%cefpodox%'
|
|---|
| 3335 | OR t.name ILIKE '%cef%'
|
|---|
| 3336 | THEN 'Cephalosporin antibiotic for skin, soft tissue and urinary tract infections'
|
|---|
| 3337 |
|
|---|
| 3338 | WHEN t.name ILIKE '%enroflox%' OR t.name ILIKE '%marboflox%'
|
|---|
| 3339 | OR t.name ILIKE '%pradoflox%' OR t.name ILIKE '%ciproflox%'
|
|---|
| 3340 | OR t.name ILIKE '%floxacin%'
|
|---|
| 3341 | THEN 'Fluoroquinolone antibiotic for gram-negative and soft tissue infections'
|
|---|
| 3342 |
|
|---|
| 3343 | WHEN t.name ILIKE '%doxycyclin%' OR t.name ILIKE '%tetracyclin%'
|
|---|
| 3344 | OR t.name ILIKE '%minocyclin%'
|
|---|
| 3345 | THEN 'Tetracycline-class antibiotic effective against intracellular and tick-borne pathogens'
|
|---|
| 3346 |
|
|---|
| 3347 | WHEN t.name ILIKE '%metronidazol%'
|
|---|
| 3348 | THEN 'Nitroimidazole antibiotic and antiprotozoal for GI and anaerobic infections'
|
|---|
| 3349 |
|
|---|
| 3350 | WHEN t.name ILIKE '%clindamycin%' OR t.name ILIKE '%lincomycin%'
|
|---|
| 3351 | THEN 'Lincosamide antibiotic for anaerobic, dental and deep tissue infections'
|
|---|
| 3352 |
|
|---|
| 3353 | WHEN t.name ILIKE '%azithromycin%' OR t.name ILIKE '%tylosin%'
|
|---|
| 3354 | OR t.name ILIKE '%erythromycin%'
|
|---|
| 3355 | THEN 'Macrolide antibiotic for respiratory and intracellular bacterial infections'
|
|---|
| 3356 |
|
|---|
| 3357 | WHEN t.name ILIKE '%trimethoprim%' OR t.name ILIKE '%sulfa%'
|
|---|
| 3358 | OR t.name ILIKE '%sulfameth%'
|
|---|
| 3359 | THEN 'Sulfonamide combination antibiotic for urinary and respiratory tract infections'
|
|---|
| 3360 |
|
|---|
| 3361 | WHEN t.name ILIKE '%vancomycin%' OR t.name ILIKE '%linezolid%'
|
|---|
| 3362 | THEN 'Reserved-use antibiotic for multidrug-resistant gram-positive infections'
|
|---|
| 3363 |
|
|---|
| 3364 | WHEN t.name ILIKE '%amikacin%' OR t.name ILIKE '%gentamicin%'
|
|---|
| 3365 | OR t.name ILIKE '%tobramycin%'
|
|---|
| 3366 | THEN 'Aminoglycoside antibiotic for serious gram-negative infections; requires renal monitoring'
|
|---|
| 3367 |
|
|---|
| 3368 | WHEN t.name ILIKE '%imipenem%' OR t.name ILIKE '%meropenem%'
|
|---|
| 3369 | OR t.name ILIKE '%ertapenem%'
|
|---|
| 3370 | THEN 'Carbapenem antibiotic reserved for multidrug-resistant bacterial infections'
|
|---|
| 3371 |
|
|---|
| 3372 | WHEN t.name ILIKE '%prednisolon%' OR t.name ILIKE '%prednison%'
|
|---|
| 3373 | THEN 'Corticosteroid for inflammatory and immune-mediated conditions'
|
|---|
| 3374 |
|
|---|
| 3375 | WHEN t.name ILIKE '%dexamethasone%'
|
|---|
| 3376 | THEN 'Potent corticosteroid for acute inflammatory and allergic reactions'
|
|---|
| 3377 |
|
|---|
| 3378 | WHEN t.name ILIKE '%methylprednisolon%'
|
|---|
| 3379 | THEN 'Intermediate-acting corticosteroid for chronic inflammatory disease'
|
|---|
| 3380 |
|
|---|
| 3381 | WHEN t.name ILIKE '%hydrocortisone%'
|
|---|
| 3382 | THEN 'Mild corticosteroid for adrenal insufficiency and mild inflammation'
|
|---|
| 3383 |
|
|---|
| 3384 | WHEN t.name ILIKE '%betamethasone%' OR t.name ILIKE '%triamcinolone%'
|
|---|
| 3385 | THEN 'Potent long-acting corticosteroid; used topically and intra-articularly'
|
|---|
| 3386 |
|
|---|
| 3387 | WHEN t.name ILIKE '%carprofen%' OR t.name ILIKE '%meloxicam%'
|
|---|
| 3388 | OR t.name ILIKE '%robenacoxib%' OR t.name ILIKE '%mavacoxib%'
|
|---|
| 3389 | OR t.name ILIKE '%grapiprant%'
|
|---|
| 3390 | THEN 'NSAID for pain and inflammation in musculoskeletal and post-operative conditions'
|
|---|
| 3391 |
|
|---|
| 3392 | WHEN t.name ILIKE '%tramadol%'
|
|---|
| 3393 | THEN 'Opioid analgesic for moderate to severe pain management'
|
|---|
| 3394 |
|
|---|
| 3395 | WHEN t.name ILIKE '%buprenorphin%'
|
|---|
| 3396 | THEN 'Partial mu-opioid agonist for perioperative and chronic pain'
|
|---|
| 3397 |
|
|---|
| 3398 | WHEN t.name ILIKE '%fentanyl%' OR t.name ILIKE '%methadon%'
|
|---|
| 3399 | OR t.name ILIKE '%morphin%'
|
|---|
| 3400 | THEN 'Full opioid agonist for perioperative and severe acute pain'
|
|---|
| 3401 |
|
|---|
| 3402 | WHEN t.name ILIKE '%gabapentin%' OR t.name ILIKE '%pregabalin%'
|
|---|
| 3403 | THEN 'Anticonvulsant and analgesic for neuropathic pain and seizure management'
|
|---|
| 3404 |
|
|---|
| 3405 | WHEN t.name ILIKE '%phenobarbit%'
|
|---|
| 3406 | THEN 'Barbiturate anticonvulsant for idiopathic epilepsy in dogs and cats'
|
|---|
| 3407 |
|
|---|
| 3408 | WHEN t.name ILIKE '%levetiracetam%'
|
|---|
| 3409 | THEN 'Novel anticonvulsant with a favourable safety profile for refractory epilepsy'
|
|---|
| 3410 |
|
|---|
| 3411 | WHEN t.name ILIKE '%potassium bromide%'
|
|---|
| 3412 | THEN 'Adjunctive anticonvulsant for dogs with refractory epilepsy'
|
|---|
| 3413 |
|
|---|
| 3414 | WHEN t.name ILIKE '%omeprazol%' OR t.name ILIKE '%pantoprazol%'
|
|---|
| 3415 | OR t.name ILIKE '%esomeprazol%'
|
|---|
| 3416 | THEN 'Proton pump inhibitor for gastric ulcer prevention and acid reflux'
|
|---|
| 3417 |
|
|---|
| 3418 | WHEN t.name ILIKE '%famotidin%' OR t.name ILIKE '%ranitidine%'
|
|---|
| 3419 | THEN 'H2 receptor blocker for gastric hyperacidity and stress ulceration'
|
|---|
| 3420 |
|
|---|
| 3421 | WHEN t.name ILIKE '%maropitant%'
|
|---|
| 3422 | THEN 'NK1 receptor antagonist antiemetic for vomiting and motion sickness'
|
|---|
| 3423 |
|
|---|
| 3424 | WHEN t.name ILIKE '%ondansetron%' OR t.name ILIKE '%dolasetron%'
|
|---|
| 3425 | THEN 'Serotonin antagonist antiemetic for chemotherapy-induced and refractory nausea'
|
|---|
| 3426 |
|
|---|
| 3427 | WHEN t.name ILIKE '%metoclopramide%'
|
|---|
| 3428 | THEN 'Prokinetic antiemetic for gastric motility disorders and vomiting'
|
|---|
| 3429 |
|
|---|
| 3430 | WHEN t.name ILIKE '%sucralfate%'
|
|---|
| 3431 | THEN 'Mucosal protectant for gastric and duodenal ulcers'
|
|---|
| 3432 |
|
|---|
| 3433 | WHEN t.name ILIKE '%lactulose%'
|
|---|
| 3434 | THEN 'Osmotic laxative for hepatic encephalopathy and chronic constipation'
|
|---|
| 3435 |
|
|---|
| 3436 | WHEN t.name ILIKE '%furosemide%' OR t.name ILIKE '%torsemide%'
|
|---|
| 3437 | THEN 'Loop diuretic for congestive heart failure and oedema management'
|
|---|
| 3438 |
|
|---|
| 3439 | WHEN t.name ILIKE '%spironolacton%'
|
|---|
| 3440 | THEN 'Potassium-sparing diuretic for cardiac and hepatic disease'
|
|---|
| 3441 |
|
|---|
| 3442 | WHEN t.name ILIKE '%enalapril%' OR t.name ILIKE '%benazepril%'
|
|---|
| 3443 | OR t.name ILIKE '%ramipril%' OR t.name ILIKE '%lisinopril%'
|
|---|
| 3444 | THEN 'ACE inhibitor for hypertension and congestive heart failure'
|
|---|
| 3445 |
|
|---|
| 3446 | WHEN t.name ILIKE '%telmisartan%' OR t.name ILIKE '%losartan%'
|
|---|
| 3447 | THEN 'Angiotensin II receptor blocker for hypertension and CKD proteinuria'
|
|---|
| 3448 |
|
|---|
| 3449 | WHEN t.name ILIKE '%amlodipine%' OR t.name ILIKE '%diltiazem%'
|
|---|
| 3450 | THEN 'Calcium channel blocker for hypertension and hypertrophic cardiomyopathy'
|
|---|
| 3451 |
|
|---|
| 3452 | WHEN t.name ILIKE '%atenolol%' OR t.name ILIKE '%metoprolol%'
|
|---|
| 3453 | OR t.name ILIKE '%propranolol%'
|
|---|
| 3454 | THEN 'Beta-blocker for arrhythmias and hypertrophic cardiomyopathy'
|
|---|
| 3455 |
|
|---|
| 3456 | WHEN t.name ILIKE '%pimobendan%'
|
|---|
| 3457 | THEN 'Inodilator for dilated cardiomyopathy and mitral valve disease'
|
|---|
| 3458 |
|
|---|
| 3459 | WHEN t.name ILIKE '%digoxin%'
|
|---|
| 3460 | THEN 'Cardiac glycoside for atrial fibrillation and congestive heart failure'
|
|---|
| 3461 |
|
|---|
| 3462 | WHEN t.name ILIKE '%sildenafil%'
|
|---|
| 3463 | THEN 'PDE-5 inhibitor for pulmonary arterial hypertension'
|
|---|
| 3464 |
|
|---|
| 3465 | WHEN t.name ILIKE '%heparin%' OR t.name ILIKE '%clopidogrel%'
|
|---|
| 3466 | THEN 'Anticoagulant / antiplatelet for thromboembolism prevention'
|
|---|
| 3467 |
|
|---|
| 3468 | WHEN t.name ILIKE '%levothyroxin%'
|
|---|
| 3469 | THEN 'Thyroid hormone replacement for canine hypothyroidism'
|
|---|
| 3470 |
|
|---|
| 3471 | WHEN t.name ILIKE '%methimazol%' OR t.name ILIKE '%carbimazol%'
|
|---|
| 3472 | THEN 'Thioamide antithyroid agent for feline hyperthyroidism'
|
|---|
| 3473 |
|
|---|
| 3474 | WHEN t.name ILIKE '%trilostane%'
|
|---|
| 3475 | THEN '3beta-HSD inhibitor for hyperadrenocorticism (Cushing disease)'
|
|---|
| 3476 |
|
|---|
| 3477 | WHEN t.name ILIKE '%mitotane%'
|
|---|
| 3478 | THEN 'Adrenocorticolytic agent for pituitary-dependent hyperadrenocorticism'
|
|---|
| 3479 |
|
|---|
| 3480 | WHEN t.name ILIKE '%insulin%'
|
|---|
| 3481 | THEN 'Insulin preparation for the management of diabetes mellitus'
|
|---|
| 3482 |
|
|---|
| 3483 | WHEN t.name ILIKE '%cyclosporin%' OR t.name ILIKE '%tacrolimus%'
|
|---|
| 3484 | THEN 'Calcineurin inhibitor immunosuppressant for immune-mediated disease'
|
|---|
| 3485 |
|
|---|
| 3486 | WHEN t.name ILIKE '%apoquel%' OR t.name ILIKE '%oclacitinib%'
|
|---|
| 3487 | THEN 'JAK inhibitor for pruritus and allergic dermatitis in dogs'
|
|---|
| 3488 |
|
|---|
| 3489 | WHEN t.name ILIKE '%hydroxyzin%' OR t.name ILIKE '%diphenhydramin%'
|
|---|
| 3490 | OR t.name ILIKE '%chlorphenamin%'
|
|---|
| 3491 | THEN 'Antihistamine for pruritic skin disease and allergic reactions'
|
|---|
| 3492 |
|
|---|
| 3493 | WHEN t.name ILIKE '%ketoconazol%' OR t.name ILIKE '%fluconazol%'
|
|---|
| 3494 | OR t.name ILIKE '%itraconazol%' OR t.name ILIKE '%voriconazol%'
|
|---|
| 3495 | OR t.name ILIKE '%terbinafin%'
|
|---|
| 3496 | THEN 'Azole or allylamine antifungal for dermatophytosis and systemic mycoses'
|
|---|
| 3497 |
|
|---|
| 3498 | WHEN t.name ILIKE '%amphotericin%'
|
|---|
| 3499 | THEN 'Polyene antifungal for systemic mycoses; nephrotoxicity monitoring required'
|
|---|
| 3500 |
|
|---|
| 3501 | WHEN t.name ILIKE '%fenbendazol%' OR t.name ILIKE '%mebendazol%'
|
|---|
| 3502 | OR t.name ILIKE '%albendazol%'
|
|---|
| 3503 | THEN 'Benzimidazole anthelmintic for roundworms, hookworms and Giardia'
|
|---|
| 3504 |
|
|---|
| 3505 | WHEN t.name ILIKE '%praziquantel%'
|
|---|
| 3506 | THEN 'Cestocidal agent for tapeworm infections in companion animals'
|
|---|
| 3507 |
|
|---|
| 3508 | WHEN t.name ILIKE '%ivermectin%' OR t.name ILIKE '%milbemycin%'
|
|---|
| 3509 | OR t.name ILIKE '%moxidectin%' OR t.name ILIKE '%selamectin%'
|
|---|
| 3510 | THEN 'Macrocyclic lactone for internal and external parasite control'
|
|---|
| 3511 |
|
|---|
| 3512 | WHEN t.name ILIKE '%pyrantel%'
|
|---|
| 3513 | THEN 'Anthelmintic for roundworm and hookworm infections'
|
|---|
| 3514 |
|
|---|
| 3515 | WHEN t.name ILIKE '%propofol%'
|
|---|
| 3516 | THEN 'Intravenous induction agent for general anaesthesia; rapid onset and recovery'
|
|---|
| 3517 |
|
|---|
| 3518 | WHEN t.name ILIKE '%alfaxalon%'
|
|---|
| 3519 | THEN 'Neurosteroid anaesthetic for induction and TIVA in cats and dogs'
|
|---|
| 3520 |
|
|---|
| 3521 | WHEN t.name ILIKE '%ketamin%'
|
|---|
| 3522 | THEN 'Dissociative anaesthetic used in combination sedation and anaesthetic protocols'
|
|---|
| 3523 |
|
|---|
| 3524 | WHEN t.name ILIKE '%midazolam%' OR t.name ILIKE '%diazepam%'
|
|---|
| 3525 | THEN 'Benzodiazepine for sedation, co-induction and status epilepticus management'
|
|---|
| 3526 |
|
|---|
| 3527 | WHEN t.name ILIKE '%medetomidin%' OR t.name ILIKE '%dexmedetomidin%'
|
|---|
| 3528 | THEN 'Alpha-2 adrenergic agonist for sedation and pre-anaesthetic medication'
|
|---|
| 3529 |
|
|---|
| 3530 | WHEN t.name ILIKE '%atropin%'
|
|---|
| 3531 | THEN 'Anticholinergic for bradycardia, organophosphate toxicosis and pre-anaesthesia'
|
|---|
| 3532 |
|
|---|
| 3533 | WHEN t.name ILIKE '%vitamin%' OR t.name ILIKE '%b12%'
|
|---|
| 3534 | OR t.name ILIKE '%cobalamin%'
|
|---|
| 3535 | THEN 'Vitamin supplement for deficiency states and supportive therapy'
|
|---|
| 3536 |
|
|---|
| 3537 | WHEN t.name ILIKE '%iron%' OR t.name ILIKE '%ferrous%'
|
|---|
| 3538 | THEN 'Iron supplement for iron-deficiency anaemia'
|
|---|
| 3539 |
|
|---|
| 3540 | WHEN t.name ILIKE '%calcium%'
|
|---|
| 3541 | THEN 'Calcium supplementation for hypocalcaemia and eclampsia'
|
|---|
| 3542 |
|
|---|
| 3543 | WHEN t.name ILIKE '%saline%' OR t.name ILIKE '%sodium chloride%'
|
|---|
| 3544 | OR t.name ILIKE '%flush%'
|
|---|
| 3545 | THEN 'Sterile isotonic saline for fluid therapy and catheter flushing'
|
|---|
| 3546 |
|
|---|
| 3547 | WHEN t.name ILIKE '%mannitol%'
|
|---|
| 3548 | THEN 'Osmotic diuretic for cerebral oedema and acute angle-closure glaucoma'
|
|---|
| 3549 |
|
|---|
| 3550 | WHEN t.name ILIKE '%dextrose%' OR t.name ILIKE '%glucose%'
|
|---|
| 3551 | THEN 'Concentrated glucose solution for hypoglycaemia; dilute before intravenous use'
|
|---|
| 3552 |
|
|---|
| 3553 | WHEN t.name ILIKE '%dopamine%' OR t.name ILIKE '%dobutamine%'
|
|---|
| 3554 | OR t.name ILIKE '%norepinephrin%' OR t.name ILIKE '%epinephrin%'
|
|---|
| 3555 | OR t.name ILIKE '%adrenalin%'
|
|---|
| 3556 | THEN 'Catecholamine vasopressor / inotrope for shock and acute haemodynamic instability'
|
|---|
| 3557 |
|
|---|
| 3558 | WHEN t.name ILIKE '%plasma%' OR t.name ILIKE '%albumin%'
|
|---|
| 3559 | THEN 'Blood product for coagulopathy, hypoproteinaemia and volume replacement'
|
|---|
| 3560 |
|
|---|
| 3561 | WHEN t.name ILIKE '%hydroxyethyl%' OR t.name ILIKE '%hetastarch%'
|
|---|
| 3562 | OR t.name ILIKE '%gelatin%'
|
|---|
| 3563 | THEN 'Colloid volume expander for hypovolaemia and hypoproteinaemia'
|
|---|
| 3564 |
|
|---|
| 3565 | WHEN t.name ILIKE '%misoprostol%'
|
|---|
| 3566 | THEN 'Prostaglandin E1 analogue for GI mucosal protection during NSAID therapy'
|
|---|
| 3567 |
|
|---|
| 3568 | WHEN t.name ILIKE '%ursodiol%' OR t.name ILIKE '%ursodeoxycholic%'
|
|---|
| 3569 | THEN 'Bile acid for cholelithiasis and chronic hepatitis management'
|
|---|
| 3570 |
|
|---|
| 3571 | WHEN t.name ILIKE '%acetylcysteine%'
|
|---|
| 3572 | THEN 'Mucolytic and antidote for paracetamol toxicosis in cats'
|
|---|
| 3573 |
|
|---|
| 3574 | ELSE 'Veterinary pharmaceutical for use in companion animals; see datasheet for full indication'
|
|---|
| 3575 | END AS description,
|
|---|
| 3576 |
|
|---|
| 3577 | NULL AS shop_item_id -- all imported medicines are not shop-linked
|
|---|
| 3578 |
|
|---|
| 3579 | FROM temp_med1 t
|
|---|
| 3580 | -- skip any that are already in medicine by name (case-insensitive)
|
|---|
| 3581 | WHERE NOT EXISTS (
|
|---|
| 3582 | SELECT 1 FROM medicine m
|
|---|
| 3583 | WHERE lower(trim(m.name)) = lower(trim(t.name))
|
|---|
| 3584 | );
|
|---|
| 3585 |
|
|---|
| 3586 |
|
|---|
| 3587 | -- ============================================================
|
|---|
| 3588 | -- STEP 3b — Bulk prescription_medicine using generate_series
|
|---|
| 3589 | -- Goal: simulate historical records reaching millions of rows.
|
|---|
| 3590 | --
|
|---|
| 3591 | -- Strategy:
|
|---|
| 3592 | -- • Generate a large set of (prescription, medicine) pairs
|
|---|
| 3593 | -- using generate_series to multiply existing prescriptions.
|
|---|
| 3594 | -- • Each prescription gets up to 6 medicines.
|
|---|
| 3595 | -- • We use hashtext for deterministic medicine assignment
|
|---|
| 3596 | -- so re-runs are idempotent with ON CONFLICT DO NOTHING.
|
|---|
| 3597 | -- ============================================================
|
|---|
| 3598 |
|
|---|
| 3599 | WITH
|
|---|
| 3600 | -- total medicines available
|
|---|
| 3601 | med_count AS (
|
|---|
| 3602 | SELECT count(*) AS total FROM medicine
|
|---|
| 3603 | ),
|
|---|
| 3604 |
|
|---|
| 3605 | -- total prescriptions
|
|---|
| 3606 | presc_count AS (
|
|---|
| 3607 | SELECT count(*) AS total FROM prescription
|
|---|
| 3608 | ),
|
|---|
| 3609 |
|
|---|
| 3610 | -- cross prescriptions with slots 1-6
|
|---|
| 3611 | slots AS (
|
|---|
| 3612 | SELECT
|
|---|
| 3613 | p.id AS prescription_id,
|
|---|
| 3614 | gs.slot
|
|---|
| 3615 | FROM prescription p
|
|---|
| 3616 | CROSS JOIN generate_series(1, 6) AS gs(slot)
|
|---|
| 3617 | ),
|
|---|
| 3618 |
|
|---|
| 3619 | -- assign a medicine to each slot deterministically
|
|---|
| 3620 | assigned AS (
|
|---|
| 3621 | SELECT
|
|---|
| 3622 | s.prescription_id,
|
|---|
| 3623 | s.slot,
|
|---|
| 3624 | (
|
|---|
| 3625 | SELECT m.id
|
|---|
| 3626 | FROM medicine m
|
|---|
| 3627 | WHERE m.id = (
|
|---|
| 3628 | (abs(hashtext(s.prescription_id::text || '-slot-' || s.slot::text))
|
|---|
| 3629 | % mc.total) + 1
|
|---|
| 3630 | )
|
|---|
| 3631 | LIMIT 1
|
|---|
| 3632 | ) AS medicine_id,
|
|---|
| 3633 | -- dosage: 1, 2 or 3 times daily
|
|---|
| 3634 | CASE (abs(hashtext(s.prescription_id::text || '-dos-' || s.slot::text)) % 3)
|
|---|
| 3635 | WHEN 0 THEN 1
|
|---|
| 3636 | WHEN 1 THEN 2
|
|---|
| 3637 | ELSE 3
|
|---|
| 3638 | END AS dosage,
|
|---|
| 3639 | -- duration: 3 to 28 days
|
|---|
| 3640 | 3 + (abs(hashtext(s.prescription_id::text || '-day-' || s.slot::text)) % 26)
|
|---|
| 3641 | AS num_days
|
|---|
| 3642 | FROM slots s
|
|---|
| 3643 | CROSS JOIN med_count mc
|
|---|
| 3644 | ),
|
|---|
| 3645 |
|
|---|
| 3646 | -- medicine IDs may not be perfectly contiguous; resolve via row_number
|
|---|
| 3647 | med_ranked AS (
|
|---|
| 3648 | SELECT id, row_number() OVER (ORDER BY id) AS rn
|
|---|
| 3649 | FROM medicine
|
|---|
| 3650 | ),
|
|---|
| 3651 |
|
|---|
| 3652 | assigned_resolved AS (
|
|---|
| 3653 | SELECT
|
|---|
| 3654 | a.prescription_id,
|
|---|
| 3655 | a.slot,
|
|---|
| 3656 | mr.id AS medicine_id,
|
|---|
| 3657 | a.dosage,
|
|---|
| 3658 | a.num_days
|
|---|
| 3659 | FROM assigned a
|
|---|
| 3660 | CROSS JOIN med_count mc
|
|---|
| 3661 | JOIN med_ranked mr
|
|---|
| 3662 | ON mr.rn = (abs(hashtext(a.prescription_id::text || '-slot-' || a.slot::text)) % mc.total) + 1
|
|---|
| 3663 | ),
|
|---|
| 3664 |
|
|---|
| 3665 | -- keep only slots within the per-prescription medicine count (2-6)
|
|---|
| 3666 | wanted AS (
|
|---|
| 3667 | SELECT
|
|---|
| 3668 | ar.prescription_id,
|
|---|
| 3669 | ar.slot,
|
|---|
| 3670 | ar.medicine_id,
|
|---|
| 3671 | ar.dosage,
|
|---|
| 3672 | ar.num_days,
|
|---|
| 3673 | -- how many medicines does this prescription want?
|
|---|
| 3674 | 2 + (abs(hashtext(ar.prescription_id::text || '-cnt')) % 5) AS want_count
|
|---|
| 3675 | FROM assigned_resolved ar
|
|---|
| 3676 | ),
|
|---|
| 3677 |
|
|---|
| 3678 | filtered AS (
|
|---|
| 3679 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 3680 | FROM wanted
|
|---|
| 3681 | WHERE slot <= want_count
|
|---|
| 3682 | ),
|
|---|
| 3683 |
|
|---|
| 3684 | -- deduplicate: if the same medicine appears twice in one prescription keep first
|
|---|
| 3685 | deduped AS (
|
|---|
| 3686 | SELECT DISTINCT ON (prescription_id, medicine_id)
|
|---|
| 3687 | prescription_id,
|
|---|
| 3688 | medicine_id,
|
|---|
| 3689 | dosage,
|
|---|
| 3690 | num_days
|
|---|
| 3691 | FROM filtered
|
|---|
| 3692 | ORDER BY prescription_id, medicine_id
|
|---|
| 3693 | )
|
|---|
| 3694 |
|
|---|
| 3695 | INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
|
|---|
| 3696 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 3697 | FROM deduped
|
|---|
| 3698 | ON CONFLICT (prescription_id, medicine_id) DO NOTHING;
|
|---|
| 3699 |
|
|---|
| 3700 |
|
|---|
| 3701 | -- ============================================================
|
|---|
| 3702 | -- STEP 3c — Historical bulk expansion
|
|---|
| 3703 | -- Simulate several years of past prescriptions by generating
|
|---|
| 3704 | -- synthetic prescription_id × medicine_id pairs via
|
|---|
| 3705 | -- generate_series, without needing real prescription rows.
|
|---|
| 3706 | --
|
|---|
| 3707 | -- We create extra prescription rows tied to existing examinations,
|
|---|
| 3708 | -- then fill prescription_medicine for them.
|
|---|
| 3709 | -- This is the cleanest way to reach millions of rows while
|
|---|
| 3710 | -- keeping referential integrity.
|
|---|
| 3711 | -- ============================================================
|
|---|
| 3712 |
|
|---|
| 3713 | -- First: generate a large batch of additional prescriptions
|
|---|
| 3714 | -- linked to completed examinations (one extra prescription
|
|---|
| 3715 | -- per examination per "historical year", 3 extra years back).
|
|---|
| 3716 |
|
|---|
| 3717 | INSERT INTO prescription (examination_id, date_start, date_end, description)
|
|---|
| 3718 | SELECT
|
|---|
| 3719 | sub.examination_id,
|
|---|
| 3720 | sub.date_start,
|
|---|
| 3721 | sub.date_end,
|
|---|
| 3722 | sub.description
|
|---|
| 3723 | FROM (
|
|---|
| 3724 | SELECT
|
|---|
| 3725 | e.id AS examination_id,
|
|---|
| 3726 | (e.date_examination - (yr.y * interval '1 year'))::date AS date_start,
|
|---|
| 3727 | (e.date_examination - (yr.y * interval '1 year')
|
|---|
| 3728 | + (7 + (abs(hashtext(e.id::text || yr.y::text)) % 21)) * interval '1 day'
|
|---|
| 3729 | )::date AS date_end,
|
|---|
| 3730 | (ARRAY[
|
|---|
| 3731 | 'Historical prescription record. Long-term medication course.',
|
|---|
| 3732 | 'Repeat prescription issued for ongoing condition management.',
|
|---|
| 3733 | 'Annual medication renewal following routine examination.',
|
|---|
| 3734 | 'Prescription reissued; owner reported good compliance.',
|
|---|
| 3735 | 'Maintenance therapy continued from previous year.',
|
|---|
| 3736 | 'Chronic condition management; dosage reviewed and maintained.',
|
|---|
| 3737 | 'Preventive medication course prescribed at annual check.',
|
|---|
| 3738 | 'Medication course extended following positive clinical response.'
|
|---|
| 3739 | ])[1 + (abs(hashtext(e.id::text || yr.y::text)) % 8)] AS description
|
|---|
| 3740 | FROM examination e
|
|---|
| 3741 | CROSS JOIN (VALUES (1),(2),(3)) AS yr(y)
|
|---|
| 3742 | WHERE e.status = 'completed'
|
|---|
| 3743 | ) sub
|
|---|
| 3744 | -- prescription has a UNIQUE constraint on examination_id,
|
|---|
| 3745 | -- so we can only have one prescription per examination.
|
|---|
| 3746 | -- Instead we'll use a workaround: generate series on medicines directly.
|
|---|
| 3747 | WHERE false; -- intentionally inserting 0 rows here; see note below
|
|---|
| 3748 |
|
|---|
| 3749 | -- NOTE: Because prescription has UNIQUE(examination_id), we cannot
|
|---|
| 3750 | -- add multiple prescriptions per examination. The volume therefore
|
|---|
| 3751 | -- comes from increasing medicines per prescription (up to 6 above)
|
|---|
| 3752 | -- combined with the full prescription set.
|
|---|
| 3753 | --
|
|---|
| 3754 | -- To genuinely reach millions of rows we expand via generate_series
|
|---|
| 3755 | -- on the medicine dimension: assign up to 20 medicines per prescription
|
|---|
| 3756 | -- using a larger series, relying on ON CONFLICT DO NOTHING to skip
|
|---|
| 3757 | -- already-inserted pairs.
|
|---|
| 3758 |
|
|---|
| 3759 | WITH
|
|---|
| 3760 | med_count AS (SELECT count(*) AS total FROM medicine),
|
|---|
| 3761 | med_ranked AS (
|
|---|
| 3762 | SELECT id, row_number() OVER (ORDER BY id) AS rn FROM medicine
|
|---|
| 3763 | ),
|
|---|
| 3764 | extra_slots AS (
|
|---|
| 3765 | SELECT
|
|---|
| 3766 | p.id AS prescription_id,
|
|---|
| 3767 | gs.slot
|
|---|
| 3768 | FROM prescription p
|
|---|
| 3769 | CROSS JOIN generate_series(7, 20) AS gs(slot)
|
|---|
| 3770 | ),
|
|---|
| 3771 | extra_assigned AS (
|
|---|
| 3772 | SELECT
|
|---|
| 3773 | es.prescription_id,
|
|---|
| 3774 | mr.id AS medicine_id,
|
|---|
| 3775 | 1 + (abs(hashtext(es.prescription_id::text || '-edos-' || es.slot::text)) % 3) AS dosage,
|
|---|
| 3776 | 3 + (abs(hashtext(es.prescription_id::text || '-eday-' || es.slot::text)) % 26) AS num_days,
|
|---|
| 3777 | -- only keep this slot if the prescription "wants" this many medicines
|
|---|
| 3778 | -- (want_count now drawn from 7-20 range for the extra batch)
|
|---|
| 3779 | 7 + (abs(hashtext(es.prescription_id::text || '-ecnt')) % 14) AS want_count,
|
|---|
| 3780 | es.slot
|
|---|
| 3781 | FROM extra_slots es
|
|---|
| 3782 | CROSS JOIN med_count mc
|
|---|
| 3783 | JOIN med_ranked mr
|
|---|
| 3784 | ON mr.rn = (abs(hashtext(es.prescription_id::text || '-eslot-' || es.slot::text)) % mc.total) + 1
|
|---|
| 3785 | ),
|
|---|
| 3786 | extra_filtered AS (
|
|---|
| 3787 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 3788 | FROM extra_assigned
|
|---|
| 3789 | WHERE slot <= want_count
|
|---|
| 3790 | ),
|
|---|
| 3791 | extra_deduped AS (
|
|---|
| 3792 | SELECT DISTINCT ON (prescription_id, medicine_id)
|
|---|
| 3793 | prescription_id, medicine_id, dosage, num_days
|
|---|
| 3794 | FROM extra_filtered
|
|---|
| 3795 | ORDER BY prescription_id, medicine_id
|
|---|
| 3796 | )
|
|---|
| 3797 | INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
|
|---|
| 3798 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 3799 | FROM extra_deduped
|
|---|
| 3800 | ON CONFLICT (prescription_id, medicine_id) DO NOTHING;
|
|---|
| 3801 |
|
|---|
| 3802 |
|
|---|
| 3803 | -- ============================================================
|
|---|
| 3804 | -- EXPAND MEDICINE TABLE
|
|---|
| 3805 | -- Combines drug bases x strengths x forms
|
|---|
| 3806 | -- Skips any name already in medicine (case-insensitive).
|
|---|
| 3807 | -- ============================================================
|
|---|
| 3808 |
|
|---|
| 3809 | WITH drug_bases AS (
|
|---|
| 3810 | SELECT unnest(ARRAY[
|
|---|
| 3811 | -- Antibiotics
|
|---|
| 3812 | 'Amoxicillin', 'Amoxicillin-Clavulanate', 'Ampicillin',
|
|---|
| 3813 | 'Cephalexin', 'Cefpodoxime', 'Cefovecin', 'Cefazolin',
|
|---|
| 3814 | 'Enrofloxacin', 'Marbofloxacin', 'Pradofloxacin', 'Orbifloxacin',
|
|---|
| 3815 | 'Doxycycline', 'Tetracycline', 'Minocycline',
|
|---|
| 3816 | 'Metronidazole', 'Tinidazole', 'Ronidazole',
|
|---|
| 3817 | 'Clindamycin', 'Lincomycin',
|
|---|
| 3818 | 'Azithromycin', 'Tylosin', 'Erythromycin',
|
|---|
| 3819 | 'Trimethoprim-Sulfamethoxazole', 'Trimethoprim-Sulfadiazine',
|
|---|
| 3820 | 'Chloramphenicol', 'Rifampicin',
|
|---|
| 3821 | 'Amikacin', 'Gentamicin', 'Tobramycin',
|
|---|
| 3822 | 'Imipenem-Cilastatin', 'Meropenem',
|
|---|
| 3823 | 'Vancomycin', 'Linezolid',
|
|---|
| 3824 | -- NSAIDs & Analgesics
|
|---|
| 3825 | 'Carprofen', 'Meloxicam', 'Robenacoxib', 'Mavacoxib',
|
|---|
| 3826 | 'Grapiprant', 'Ketoprofen', 'Tolfenamic Acid',
|
|---|
| 3827 | 'Tramadol', 'Buprenorphine', 'Methadone', 'Morphine',
|
|---|
| 3828 | 'Fentanyl', 'Butorphanol', 'Nalbuphine',
|
|---|
| 3829 | 'Gabapentin', 'Pregabalin', 'Amantadine',
|
|---|
| 3830 | -- Corticosteroids
|
|---|
| 3831 | 'Prednisolone', 'Prednisone', 'Dexamethasone',
|
|---|
| 3832 | 'Methylprednisolone', 'Hydrocortisone', 'Betamethasone',
|
|---|
| 3833 | 'Triamcinolone', 'Budesonide', 'Fluticasone',
|
|---|
| 3834 | -- Cardiac
|
|---|
| 3835 | 'Furosemide', 'Torsemide', 'Spironolactone',
|
|---|
| 3836 | 'Enalapril', 'Benazepril', 'Ramipril', 'Lisinopril',
|
|---|
| 3837 | 'Telmisartan', 'Amlodipine', 'Diltiazem',
|
|---|
| 3838 | 'Atenolol', 'Metoprolol', 'Propranolol', 'Sotalol',
|
|---|
| 3839 | 'Pimobendan', 'Digoxin', 'Sildenafil', 'Clopidogrel',
|
|---|
| 3840 | 'Heparin', 'Warfarin',
|
|---|
| 3841 | -- GI
|
|---|
| 3842 | 'Omeprazole', 'Pantoprazole', 'Esomeprazole',
|
|---|
| 3843 | 'Famotidine', 'Ranitidine', 'Sucralfate',
|
|---|
| 3844 | 'Metoclopramide', 'Cisapride', 'Ondansetron',
|
|---|
| 3845 | 'Maropitant', 'Dolasetron', 'Prochlorperazine',
|
|---|
| 3846 | 'Lactulose', 'Loperamide', 'Bismuth Subsalicylate',
|
|---|
| 3847 | 'Misoprostol', 'Ursodiol',
|
|---|
| 3848 | -- Anticonvulsants
|
|---|
| 3849 | 'Phenobarbital', 'Potassium Bromide', 'Levetiracetam',
|
|---|
| 3850 | 'Zonisamide', 'Gabapentin', 'Pregabalin', 'Imepitoin',
|
|---|
| 3851 | -- Endocrine
|
|---|
| 3852 | 'Levothyroxine', 'Methimazole', 'Carbimazole',
|
|---|
| 3853 | 'Trilostane', 'Mitotane', 'Insulin Glargine',
|
|---|
| 3854 | 'Insulin NPH', 'Cabergoline', 'Deslorelin',
|
|---|
| 3855 | -- Immunosuppressants / Dermatology
|
|---|
| 3856 | 'Cyclosporine', 'Tacrolimus', 'Azathioprine',
|
|---|
| 3857 | 'Mycophenolate Mofetil', 'Chlorambucil',
|
|---|
| 3858 | 'Oclacitinib', 'Lokivetmab',
|
|---|
| 3859 | 'Hydroxyzine', 'Diphenhydramine', 'Chlorphenamine',
|
|---|
| 3860 | 'Cetirizine', 'Loratadine',
|
|---|
| 3861 | -- Antifungals
|
|---|
| 3862 | 'Ketoconazole', 'Fluconazole', 'Itraconazole',
|
|---|
| 3863 | 'Voriconazole', 'Terbinafine', 'Amphotericin B',
|
|---|
| 3864 | 'Griseofulvin', 'Clotrimazole', 'Miconazole',
|
|---|
| 3865 | -- Antiparasitics
|
|---|
| 3866 | 'Fenbendazole', 'Mebendazole', 'Albendazole',
|
|---|
| 3867 | 'Praziquantel', 'Epsiprantel',
|
|---|
| 3868 | 'Ivermectin', 'Milbemycin Oxime', 'Moxidectin',
|
|---|
| 3869 | 'Selamectin', 'Pyrantel Pamoate', 'Nitenpyram',
|
|---|
| 3870 | 'Afoxolaner', 'Fluralaner', 'Sarolaner', 'Lotilaner',
|
|---|
| 3871 | -- Anaesthetics / Sedatives
|
|---|
| 3872 | 'Propofol', 'Alfaxalone', 'Ketamine', 'Tiletamine',
|
|---|
| 3873 | 'Midazolam', 'Diazepam', 'Zolazepam',
|
|---|
| 3874 | 'Medetomidine', 'Dexmedetomidine', 'Romifidine',
|
|---|
| 3875 | 'Atropine', 'Glycopyrrolate',
|
|---|
| 3876 | 'Isoflurane', 'Sevoflurane',
|
|---|
| 3877 | -- Fluids / Electrolytes
|
|---|
| 3878 | 'Sodium Chloride 0.9%', 'Lactated Ringers Solution',
|
|---|
| 3879 | 'Hartmann Solution', 'Dextrose 5%', 'Dextrose 50%',
|
|---|
| 3880 | 'Potassium Chloride', 'Sodium Bicarbonate',
|
|---|
| 3881 | 'Calcium Gluconate', 'Mannitol 20%',
|
|---|
| 3882 | 'Hydroxyethyl Starch 6%', 'Gelatin 4%',
|
|---|
| 3883 | -- Supportive / Other
|
|---|
| 3884 | 'Acetylcysteine', 'S-Adenosylmethionine', 'Silymarin',
|
|---|
| 3885 | 'Vitamin B12', 'Iron Dextran', 'Folic Acid',
|
|---|
| 3886 | 'Vitamin K1', 'Doxapram', 'Atipamezole',
|
|---|
| 3887 | 'Naloxone', 'Flumazenil', 'Pralidoxime',
|
|---|
| 3888 | 'Dopamine', 'Dobutamine', 'Norepinephrine',
|
|---|
| 3889 | 'Epinephrine', 'Vasopressin',
|
|---|
| 3890 | 'Allopurinol', 'Colchicine', 'Pentoxifylline',
|
|---|
| 3891 | 'Pilocarpine', 'Dorzolamide', 'Latanoprost'
|
|---|
| 3892 | ]) AS base
|
|---|
| 3893 | ),
|
|---|
| 3894 |
|
|---|
| 3895 | strengths AS (
|
|---|
| 3896 | SELECT unnest(ARRAY[
|
|---|
| 3897 | '2.5mg', '5mg', '10mg', '12.5mg', '20mg', '25mg',
|
|---|
| 3898 | '30mg', '40mg', '50mg', '75mg', '100mg', '125mg',
|
|---|
| 3899 | '150mg', '200mg', '250mg', '300mg', '400mg', '500mg',
|
|---|
| 3900 | '600mg', '750mg', '1g',
|
|---|
| 3901 | '0.5mg/ml', '1mg/ml', '2mg/ml', '2.5mg/ml', '4mg/ml',
|
|---|
| 3902 | '5mg/ml', '10mg/ml', '20mg/ml', '50mg/ml', '100mg/ml',
|
|---|
| 3903 | '1.5mg/ml', '0.1mg/ml', '0.3mg/ml', '0.5%', '1%', '2%',
|
|---|
| 3904 | '2.27mg', '3.6mg', '16mg', '68mg', '136mg'
|
|---|
| 3905 | ]) AS strength
|
|---|
| 3906 | ),
|
|---|
| 3907 |
|
|---|
| 3908 | forms AS (
|
|---|
| 3909 | SELECT unnest(ARRAY[
|
|---|
| 3910 | 'Tablets', 'Chewable Tablets', 'Film-Coated Tablets',
|
|---|
| 3911 | 'Capsules', 'Oral Solution', 'Oral Suspension',
|
|---|
| 3912 | 'Injection', 'Lyophilisate for Injection',
|
|---|
| 3913 | 'Spot-On Solution', 'Transdermal Gel',
|
|---|
| 3914 | 'Ear Drops', 'Eye Drops', 'Ophthalmic Ointment',
|
|---|
| 3915 | 'Powder for Oral Solution', 'Granules',
|
|---|
| 3916 | 'Prolonged-Release Tablets', 'Soft Chews'
|
|---|
| 3917 | ]) AS form
|
|---|
| 3918 | ),
|
|---|
| 3919 |
|
|---|
| 3920 | -- not all base+strength+form combos make sense;
|
|---|
| 3921 | -- filter to plausible combinations
|
|---|
| 3922 | plausible AS (
|
|---|
| 3923 | SELECT
|
|---|
| 3924 | b.base || ' ' || s.strength || ' ' || f.form AS med_name,
|
|---|
| 3925 | -- assign manufacturer
|
|---|
| 3926 | (ARRAY[
|
|---|
| 3927 | 'Zoetis Inc.', 'Boehringer Ingelheim', 'Elanco Animal Health',
|
|---|
| 3928 | 'Virbac Animal Health', 'Dechra Veterinary', 'Norbrook Laboratories',
|
|---|
| 3929 | 'Vetoquinol', 'Bayer Animal Health', 'MSD Animal Health',
|
|---|
| 3930 | 'Pfizer Animal Health', 'Jurox Animal Health',
|
|---|
| 3931 | 'Intervet-Schering Plough', 'Novartis Animal Health',
|
|---|
| 3932 | 'Merial', 'Orion Pharma'
|
|---|
| 3933 | ])[1 + (abs(hashtext(b.base || s.strength || f.form)) % 15)] AS manufacturer
|
|---|
| 3934 | FROM drug_bases b
|
|---|
| 3935 | CROSS JOIN strengths s
|
|---|
| 3936 | CROSS JOIN forms f
|
|---|
| 3937 | WHERE
|
|---|
| 3938 | -- injections go with mg/ml or % strengths
|
|---|
| 3939 | (f.form IN ('Injection','Lyophilisate for Injection',
|
|---|
| 3940 | 'Eye Drops','Ear Drops','Spot-On Solution',
|
|---|
| 3941 | 'Transdermal Gel','Ophthalmic Ointment')
|
|---|
| 3942 | AND (s.strength ~ 'mg/ml' OR s.strength ~ '%' OR s.strength ~ 'mg$'))
|
|---|
| 3943 | OR
|
|---|
| 3944 | -- oral solids go with mg or g strengths
|
|---|
| 3945 | (f.form IN ('Tablets','Chewable Tablets','Film-Coated Tablets',
|
|---|
| 3946 | 'Prolonged-Release Tablets','Capsules',
|
|---|
| 3947 | 'Powder for Oral Solution','Granules',
|
|---|
| 3948 | 'Soft Chews')
|
|---|
| 3949 | AND s.strength ~ '^[0-9]' AND s.strength NOT LIKE '%ml%'
|
|---|
| 3950 | AND s.strength NOT LIKE '%%')
|
|---|
| 3951 | OR
|
|---|
| 3952 | -- liquids go with mg/ml or %
|
|---|
| 3953 | (f.form IN ('Oral Solution','Oral Suspension')
|
|---|
| 3954 | AND (s.strength ~ 'mg/ml' OR s.strength ~ '%'
|
|---|
| 3955 | OR (s.strength ~ '^[0-9]' AND s.strength NOT LIKE '%ml%')))
|
|---|
| 3956 | -- exclude nonsensical size+form pairs (very large mg in eye drops etc.)
|
|---|
| 3957 | AND NOT (f.form IN ('Eye Drops','Ear Drops')
|
|---|
| 3958 | AND s.strength IN ('500mg','750mg','1g','600mg','400mg',
|
|---|
| 3959 | '300mg','250mg','200mg','150mg'))
|
|---|
| 3960 | AND NOT (f.form = 'Spot-On Solution'
|
|---|
| 3961 | AND s.strength NOT IN ('2.27mg','3.6mg','16mg','68mg','136mg',
|
|---|
| 3962 | '0.5%','1%','2%','10mg/ml','50mg/ml'))
|
|---|
| 3963 | ),
|
|---|
| 3964 |
|
|---|
| 3965 | -- cap at 5000 new medicines
|
|---|
| 3966 | ranked AS (
|
|---|
| 3967 | SELECT
|
|---|
| 3968 | med_name,
|
|---|
| 3969 | manufacturer,
|
|---|
| 3970 | row_number() OVER (ORDER BY md5(med_name)) AS rn
|
|---|
| 3971 | FROM plausible
|
|---|
| 3972 | )
|
|---|
| 3973 |
|
|---|
| 3974 | INSERT INTO medicine (name, manufacturer, description, shop_item_id)
|
|---|
| 3975 | SELECT
|
|---|
| 3976 | r.med_name,
|
|---|
| 3977 | r.manufacturer,
|
|---|
| 3978 | 'Veterinary pharmaceutical for use in companion animals; see datasheet for full indication.' AS description,
|
|---|
| 3979 | NULL
|
|---|
| 3980 | FROM ranked r
|
|---|
| 3981 | WHERE r.rn <= 5000
|
|---|
| 3982 | AND NOT EXISTS (
|
|---|
| 3983 | SELECT 1 FROM medicine m
|
|---|
| 3984 | WHERE lower(trim(m.name)) = lower(trim(r.med_name))
|
|---|
| 3985 | );
|
|---|
| 3986 |
|
|---|
| 3987 |
|
|---|
| 3988 |
|
|---|
| 3989 | -- ============================================================
|
|---|
| 3990 | -- More addresses — add 1600 more (for no duplicates)
|
|---|
| 3991 | -- ============================================================
|
|---|
| 3992 |
|
|---|
| 3993 | TRUNCATE temp_addresses;
|
|---|
| 3994 |
|
|---|
| 3995 | COPY temp_addresses (address, city, state, zip)
|
|---|
| 3996 | FROM 'C:/Program Files/PostgreSQL/18/data/temp_files/addresses.csv'
|
|---|
| 3997 | DELIMITER ',' CSV HEADER;
|
|---|
| 3998 |
|
|---|
| 3999 | UPDATE temp_addresses SET address = TRIM(address);
|
|---|
| 4000 | UPDATE temp_addresses SET city = TRIM(city);
|
|---|
| 4001 | UPDATE temp_addresses SET state = TRIM(state);
|
|---|
| 4002 | UPDATE temp_addresses SET zip = TRIM(zip);
|
|---|
| 4003 |
|
|---|
| 4004 | -- ============================================================
|
|---|
| 4005 | -- More owners — add 1600 more (total ~2000)
|
|---|
| 4006 | -- ============================================================
|
|---|
| 4007 |
|
|---|
| 4008 | WITH male_names_sample AS (
|
|---|
| 4009 | SELECT name FROM temp_male_names ORDER BY random() LIMIT 5000
|
|---|
| 4010 | ),
|
|---|
| 4011 | female_names_sample AS (
|
|---|
| 4012 | SELECT name FROM temp_female_names ORDER BY random() LIMIT 5000
|
|---|
| 4013 | ),
|
|---|
| 4014 | male_pool AS (
|
|---|
| 4015 | SELECT fn.name AS first_name, ln.surname AS last_name, 'M' AS gender
|
|---|
| 4016 | FROM male_names_sample fn
|
|---|
| 4017 | CROSS JOIN temp_surnames ln
|
|---|
| 4018 | ORDER BY random()
|
|---|
| 4019 | LIMIT 800
|
|---|
| 4020 | ),
|
|---|
| 4021 | female_pool AS (
|
|---|
| 4022 | SELECT fn.name AS first_name, ln.surname AS last_name, 'F' AS gender
|
|---|
| 4023 | FROM female_names_sample fn
|
|---|
| 4024 | CROSS JOIN temp_surnames ln
|
|---|
| 4025 | ORDER BY random()
|
|---|
| 4026 | LIMIT 800
|
|---|
| 4027 | ),
|
|---|
| 4028 | all_names AS (
|
|---|
| 4029 | SELECT first_name, last_name, gender FROM male_pool
|
|---|
| 4030 | UNION ALL
|
|---|
| 4031 | SELECT first_name, last_name, gender FROM female_pool
|
|---|
| 4032 | ),
|
|---|
| 4033 | numbered AS (
|
|---|
| 4034 | SELECT first_name, last_name, gender,
|
|---|
| 4035 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 4036 | FROM all_names
|
|---|
| 4037 | ),
|
|---|
| 4038 | addr_count AS (
|
|---|
| 4039 | SELECT count(*) AS cnt FROM temp_addresses
|
|---|
| 4040 | ),
|
|---|
| 4041 | addr_ranked AS (
|
|---|
| 4042 | SELECT
|
|---|
| 4043 | address || ', ' || city || ', ' || state || ' ' || zip AS full_address,
|
|---|
| 4044 | row_number() OVER (ORDER BY id) AS rn
|
|---|
| 4045 | FROM temp_addresses
|
|---|
| 4046 | ),
|
|---|
| 4047 | shuffled_phones AS (
|
|---|
| 4048 | SELECT
|
|---|
| 4049 | ((row_number() OVER (ORDER BY random()) % 9) + 1)::text AS d1,
|
|---|
| 4050 | lpad(((row_number() OVER (ORDER BY random()) * 73) % 900 + 100)::text, 3, '0') AS d2,
|
|---|
| 4051 | lpad(((row_number() OVER (ORDER BY random()) * 97) % 900 + 100)::text, 3, '0') AS d3,
|
|---|
| 4052 | row_number() OVER (ORDER BY random()) AS rn
|
|---|
| 4053 | FROM generate_series(1, 1600)
|
|---|
| 4054 | )
|
|---|
| 4055 | INSERT INTO owner (first_name, last_name, phone, email, address, gender)
|
|---|
| 4056 | SELECT
|
|---|
| 4057 | n.first_name,
|
|---|
| 4058 | n.last_name,
|
|---|
| 4059 | '+389 7' || p.d1 || ' ' || p.d2 || ' ' || p.d3 AS phone,
|
|---|
| 4060 | lower(n.first_name) || '.' || lower(n.last_name)
|
|---|
| 4061 | || n.rn::text || '@gmail.com' AS email,
|
|---|
| 4062 | ar.full_address AS address,
|
|---|
| 4063 | n.gender
|
|---|
| 4064 | FROM numbered n
|
|---|
| 4065 | JOIN shuffled_phones p ON p.rn = n.rn
|
|---|
| 4066 | CROSS JOIN addr_count ac
|
|---|
| 4067 | JOIN addr_ranked ar
|
|---|
| 4068 | ON ar.rn = ((n.rn - 1) % ac.cnt) + 1
|
|---|
| 4069 | LIMIT 1600;
|
|---|
| 4070 |
|
|---|
| 4071 | -- ============================================================
|
|---|
| 4072 | -- MORE PETS — ~3 pets per new owner on average (~5000 more)
|
|---|
| 4073 | -- ============================================================
|
|---|
| 4074 |
|
|---|
| 4075 | WITH new_owners AS (
|
|---|
| 4076 | -- owners that have no pets yet
|
|---|
| 4077 | SELECT o.id
|
|---|
| 4078 | FROM owner o
|
|---|
| 4079 | LEFT JOIN pet p ON p.owner_id = o.id
|
|---|
| 4080 | WHERE p.id IS NULL
|
|---|
| 4081 | ),
|
|---|
| 4082 | breed_counts AS (
|
|---|
| 4083 | SELECT
|
|---|
| 4084 | (SELECT count(*) FROM temp_breeds_mammal) AS mammal_cnt,
|
|---|
| 4085 | (SELECT count(*) FROM temp_breeds_bird) AS bird_cnt,
|
|---|
| 4086 | (SELECT count(*) FROM temp_breeds_fish) AS fish_cnt,
|
|---|
| 4087 | (SELECT count(*) FROM temp_breeds_reptile) AS reptile_cnt,
|
|---|
| 4088 | (SELECT count(*) FROM temp_breeds_amphibian) AS amphibian_cnt,
|
|---|
| 4089 | (SELECT count(*) FROM temp_pet_names) AS names_cnt,
|
|---|
| 4090 | (SELECT count(*) FROM temp_medical_history) AS history_cnt
|
|---|
| 4091 | ),
|
|---|
| 4092 | -- expand: each owner gets 2-4 pets
|
|---|
| 4093 | owner_slots AS (
|
|---|
| 4094 | SELECT
|
|---|
| 4095 | o.id AS owner_id,
|
|---|
| 4096 | gs.slot
|
|---|
| 4097 | FROM new_owners o
|
|---|
| 4098 | CROSS JOIN generate_series(1, 4) AS gs(slot)
|
|---|
| 4099 | -- keep slot if <= random per-owner pet count (2-4)
|
|---|
| 4100 | WHERE gs.slot <= 2 + (abs(hashtext(o.id::text || 'petcnt')) % 3)
|
|---|
| 4101 | ),
|
|---|
| 4102 | typed AS (
|
|---|
| 4103 | SELECT
|
|---|
| 4104 | os.owner_id,
|
|---|
| 4105 | os.slot,
|
|---|
| 4106 | CASE (abs(hashtext(os.owner_id::text || os.slot::text || 'type')) % 10)
|
|---|
| 4107 | WHEN 0 THEN 'mammal'
|
|---|
| 4108 | WHEN 1 THEN 'mammal'
|
|---|
| 4109 | WHEN 2 THEN 'mammal'
|
|---|
| 4110 | WHEN 3 THEN 'mammal'
|
|---|
| 4111 | WHEN 4 THEN 'mammal'
|
|---|
| 4112 | WHEN 5 THEN 'mammal'
|
|---|
| 4113 | WHEN 6 THEN 'bird'
|
|---|
| 4114 | WHEN 7 THEN 'reptile'
|
|---|
| 4115 | WHEN 8 THEN 'fish'
|
|---|
| 4116 | ELSE 'amphibian'
|
|---|
| 4117 | END AS type
|
|---|
| 4118 | FROM owner_slots os
|
|---|
| 4119 | ),
|
|---|
| 4120 | names_ranked AS (
|
|---|
| 4121 | SELECT name, row_number() OVER (ORDER BY id) AS rn FROM temp_pet_names
|
|---|
| 4122 | ),
|
|---|
| 4123 | history_ranked AS (
|
|---|
| 4124 | SELECT history, row_number() OVER (ORDER BY id) AS rn FROM temp_medical_history
|
|---|
| 4125 | ),
|
|---|
| 4126 | mammal_ranked AS (SELECT breed_name, row_number() OVER (ORDER BY id) AS rn FROM temp_breeds_mammal),
|
|---|
| 4127 | bird_ranked AS (SELECT breed_name, row_number() OVER (ORDER BY id) AS rn FROM temp_breeds_bird),
|
|---|
| 4128 | fish_ranked AS (SELECT breed_name, row_number() OVER (ORDER BY id) AS rn FROM temp_breeds_fish),
|
|---|
| 4129 | reptile_ranked AS (SELECT breed_name, row_number() OVER (ORDER BY id) AS rn FROM temp_breeds_reptile),
|
|---|
| 4130 | amphibian_ranked AS (SELECT breed_name, row_number() OVER (ORDER BY id) AS rn FROM temp_breeds_amphibian)
|
|---|
| 4131 |
|
|---|
| 4132 | INSERT INTO pet (name, is_active, type, breed, age, medical_history, owner_id)
|
|---|
| 4133 | SELECT
|
|---|
| 4134 | nr.name,
|
|---|
| 4135 | (abs(hashtext(t.owner_id::text || t.slot::text || 'active')) % 10 < 9) AS is_active,
|
|---|
| 4136 | t.type,
|
|---|
| 4137 | CASE t.type
|
|---|
| 4138 | WHEN 'mammal' THEN mbr.breed_name
|
|---|
| 4139 | WHEN 'bird' THEN bbr.breed_name
|
|---|
| 4140 | WHEN 'fish' THEN fbr.breed_name
|
|---|
| 4141 | WHEN 'reptile' THEN rbr.breed_name
|
|---|
| 4142 | WHEN 'amphibian' THEN abr.breed_name
|
|---|
| 4143 | END AS breed,
|
|---|
| 4144 | CASE t.type
|
|---|
| 4145 | WHEN 'mammal' THEN (abs(hashtext(t.owner_id::text || t.slot::text || 'age')) % 240)
|
|---|
| 4146 | WHEN 'bird' THEN (abs(hashtext(t.owner_id::text || t.slot::text || 'age')) % 720)
|
|---|
| 4147 | WHEN 'reptile' THEN (abs(hashtext(t.owner_id::text || t.slot::text || 'age')) % 600)
|
|---|
| 4148 | WHEN 'fish' THEN (abs(hashtext(t.owner_id::text || t.slot::text || 'age')) % 240)
|
|---|
| 4149 | WHEN 'amphibian' THEN (abs(hashtext(t.owner_id::text || t.slot::text || 'age')) % 360)
|
|---|
| 4150 | END AS age,
|
|---|
| 4151 | hr.history,
|
|---|
| 4152 | t.owner_id
|
|---|
| 4153 | FROM typed t
|
|---|
| 4154 | CROSS JOIN breed_counts bc
|
|---|
| 4155 | JOIN names_ranked nr
|
|---|
| 4156 | ON nr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'nm')) % bc.names_cnt) + 1
|
|---|
| 4157 | JOIN history_ranked hr
|
|---|
| 4158 | ON hr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'hi')) % bc.history_cnt) + 1
|
|---|
| 4159 | LEFT JOIN mammal_ranked mbr
|
|---|
| 4160 | ON t.type = 'mammal'
|
|---|
| 4161 | AND mbr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'mb')) % bc.mammal_cnt) + 1
|
|---|
| 4162 | LEFT JOIN bird_ranked bbr
|
|---|
| 4163 | ON t.type = 'bird'
|
|---|
| 4164 | AND bbr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'bb')) % bc.bird_cnt) + 1
|
|---|
| 4165 | LEFT JOIN fish_ranked fbr
|
|---|
| 4166 | ON t.type = 'fish'
|
|---|
| 4167 | AND fbr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'fb')) % bc.fish_cnt) + 1
|
|---|
| 4168 | LEFT JOIN reptile_ranked rbr
|
|---|
| 4169 | ON t.type = 'reptile'
|
|---|
| 4170 | AND rbr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'rb')) % bc.reptile_cnt) + 1
|
|---|
| 4171 | LEFT JOIN amphibian_ranked abr
|
|---|
| 4172 | ON t.type = 'amphibian'
|
|---|
| 4173 | AND abr.rn = (abs(hashtext(t.owner_id::text || t.slot::text || 'ab')) % bc.amphibian_cnt) + 1;
|
|---|
| 4174 |
|
|---|
| 4175 |
|
|---|
| 4176 | -- ============================================================
|
|---|
| 4177 | -- Large tables
|
|---|
| 4178 | -- TRUNCATE dependent tables (reverse FK order)
|
|---|
| 4179 | -- ============================================================
|
|---|
| 4180 |
|
|---|
| 4181 | TRUNCATE prescription_medicine CASCADE;
|
|---|
| 4182 | TRUNCATE prescription CASCADE;
|
|---|
| 4183 | TRUNCATE treatment_attribute_value CASCADE;
|
|---|
| 4184 | TRUNCATE treatment CASCADE;
|
|---|
| 4185 | TRUNCATE examination CASCADE;
|
|---|
| 4186 | TRUNCATE appointment CASCADE;
|
|---|
| 4187 |
|
|---|
| 4188 |
|
|---|
| 4189 | -- ============================================================
|
|---|
| 4190 | -- APPOINTMENT — 850,000 rows
|
|---|
| 4191 | -- ============================================================
|
|---|
| 4192 |
|
|---|
| 4193 | INSERT INTO appointment (date_appointment, reason, phone, owner_id, pet_id)
|
|---|
| 4194 | WITH owner_pet_pairs AS (
|
|---|
| 4195 | SELECT
|
|---|
| 4196 | o.id AS owner_id,
|
|---|
| 4197 | o.phone AS phone,
|
|---|
| 4198 | p.id AS pet_id,
|
|---|
| 4199 | row_number() OVER (ORDER BY o.id, p.id) AS rn
|
|---|
| 4200 | FROM owner o
|
|---|
| 4201 | JOIN pet p ON p.owner_id = o.id
|
|---|
| 4202 | ),
|
|---|
| 4203 | pair_count AS (
|
|---|
| 4204 | SELECT count(*) AS cnt FROM owner_pet_pairs
|
|---|
| 4205 | )
|
|---|
| 4206 | SELECT
|
|---|
| 4207 | (CURRENT_DATE - (abs(hashtext(gs.n::text || 'apdate')) % 1825))::date AS date_appointment,
|
|---|
| 4208 |
|
|---|
| 4209 | (ARRAY[
|
|---|
| 4210 | 'Annual wellness check',
|
|---|
| 4211 | 'Vaccination booster',
|
|---|
| 4212 | 'Limping / lameness',
|
|---|
| 4213 | 'Vomiting and lethargy',
|
|---|
| 4214 | 'Skin rash and itching',
|
|---|
| 4215 | 'Ear infection suspected',
|
|---|
| 4216 | 'Eye discharge and redness',
|
|---|
| 4217 | 'Dental check-up',
|
|---|
| 4218 | 'Weight loss and poor appetite',
|
|---|
| 4219 | 'Diarrhoea for more than 2 days',
|
|---|
| 4220 | 'Post-operative follow-up',
|
|---|
| 4221 | 'Suspected urinary tract infection',
|
|---|
| 4222 | 'Respiratory difficulty',
|
|---|
| 4223 | 'Wound assessment',
|
|---|
| 4224 | 'Parasite prevention consultation',
|
|---|
| 4225 | 'Behavioural changes',
|
|---|
| 4226 | 'Mass / lump noticed',
|
|---|
| 4227 | 'Allergic reaction',
|
|---|
| 4228 | 'Pre-surgical blood work',
|
|---|
| 4229 | 'General health concern',
|
|---|
| 4230 | 'Annual vaccination',
|
|---|
| 4231 | 'Rabies vaccine booster',
|
|---|
| 4232 | 'Core vaccine schedule - puppy/kitten',
|
|---|
| 4233 | 'Bordetella vaccination',
|
|---|
| 4234 | 'Leptospirosis booster',
|
|---|
| 4235 | 'Feline herpesvirus / calicivirus / panleukopenia combo',
|
|---|
| 4236 | 'Canine distemper / parvovirus booster',
|
|---|
| 4237 | 'Vaccine certificate needed for travel',
|
|---|
| 4238 | 'First vaccination - new pet',
|
|---|
| 4239 | 'Overdue vaccination catch-up'
|
|---|
| 4240 | ])[1 + (abs(hashtext(gs.n::text || 'rsn')) % 30)] AS reason,
|
|---|
| 4241 |
|
|---|
| 4242 | op.phone,
|
|---|
| 4243 | op.owner_id,
|
|---|
| 4244 | op.pet_id
|
|---|
| 4245 |
|
|---|
| 4246 | FROM generate_series(1, 850000) AS gs(n)
|
|---|
| 4247 | CROSS JOIN pair_count pc
|
|---|
| 4248 | JOIN owner_pet_pairs op
|
|---|
| 4249 | ON op.rn = ((gs.n - 1) % pc.cnt) + 1;
|
|---|
| 4250 |
|
|---|
| 4251 |
|
|---|
| 4252 | -- ============================================================
|
|---|
| 4253 | -- EXAMINATION — 720,000 rows
|
|---|
| 4254 | -- Takes first 720k appointments ordered by id
|
|---|
| 4255 | -- ~80% completed, ~13% cancelled, ~7% scheduled
|
|---|
| 4256 | -- ============================================================
|
|---|
| 4257 |
|
|---|
| 4258 | INSERT INTO examination (date_examination, status, description, appointment_id, employee_id, examination_room_id)
|
|---|
| 4259 | WITH apt_sample AS (
|
|---|
| 4260 | SELECT
|
|---|
| 4261 | a.id AS appointment_id,
|
|---|
| 4262 | a.date_appointment
|
|---|
| 4263 | FROM appointment a
|
|---|
| 4264 | ORDER BY a.id
|
|---|
| 4265 | LIMIT 720000
|
|---|
| 4266 | ),
|
|---|
| 4267 | emp_ranked AS (
|
|---|
| 4268 | SELECT id, row_number() OVER (ORDER BY id) AS rn
|
|---|
| 4269 | FROM employee WHERE role_id = 2
|
|---|
| 4270 | ),
|
|---|
| 4271 | emp_count AS (
|
|---|
| 4272 | SELECT count(*) AS cnt FROM employee WHERE role_id = 2
|
|---|
| 4273 | ),
|
|---|
| 4274 | room_ranked AS (
|
|---|
| 4275 | SELECT id, row_number() OVER (ORDER BY id) AS rn
|
|---|
| 4276 | FROM examination_room WHERE type = 'examination'
|
|---|
| 4277 | ),
|
|---|
| 4278 | room_count AS (
|
|---|
| 4279 | SELECT count(*) AS cnt FROM examination_room WHERE type = 'examination'
|
|---|
| 4280 | )
|
|---|
| 4281 | SELECT
|
|---|
| 4282 | (a.date_appointment + (abs(hashtext(a.appointment_id::text || 'edate')) % 8))::date AS date_examination,
|
|---|
| 4283 |
|
|---|
| 4284 | CASE (abs(hashtext(a.appointment_id::text || 'stat')) % 100)
|
|---|
| 4285 | WHEN 0 THEN 'cancelled'
|
|---|
| 4286 | WHEN 1 THEN 'cancelled'
|
|---|
| 4287 | WHEN 2 THEN 'cancelled'
|
|---|
| 4288 | WHEN 3 THEN 'cancelled'
|
|---|
| 4289 | WHEN 4 THEN 'cancelled'
|
|---|
| 4290 | WHEN 5 THEN 'cancelled'
|
|---|
| 4291 | WHEN 6 THEN 'cancelled'
|
|---|
| 4292 | WHEN 7 THEN 'cancelled'
|
|---|
| 4293 | WHEN 8 THEN 'cancelled'
|
|---|
| 4294 | WHEN 9 THEN 'cancelled'
|
|---|
| 4295 | WHEN 10 THEN 'cancelled'
|
|---|
| 4296 | WHEN 11 THEN 'cancelled'
|
|---|
| 4297 | WHEN 12 THEN 'cancelled'
|
|---|
| 4298 | WHEN 13 THEN 'scheduled'
|
|---|
| 4299 | WHEN 14 THEN 'scheduled'
|
|---|
| 4300 | WHEN 15 THEN 'scheduled'
|
|---|
| 4301 | WHEN 16 THEN 'scheduled'
|
|---|
| 4302 | WHEN 17 THEN 'scheduled'
|
|---|
| 4303 | WHEN 18 THEN 'scheduled'
|
|---|
| 4304 | WHEN 19 THEN 'scheduled'
|
|---|
| 4305 | ELSE 'completed'
|
|---|
| 4306 | END AS status,
|
|---|
| 4307 |
|
|---|
| 4308 | (ARRAY[
|
|---|
| 4309 | 'Patient presented for routine examination. Vitals within normal limits.',
|
|---|
| 4310 | 'Initial assessment completed. Further diagnostics recommended.',
|
|---|
| 4311 | 'Physical examination performed. Owner advised on treatment plan.',
|
|---|
| 4312 | 'Patient examined; mild clinical signs noted. Medication prescribed.',
|
|---|
| 4313 | 'Thorough examination carried out. No acute concerns identified.',
|
|---|
| 4314 | 'Follow-up examination. Condition improving since last visit.',
|
|---|
| 4315 | 'Examination completed. Lab samples collected for analysis.',
|
|---|
| 4316 | 'Clinical signs assessed. Dietary modification recommended.',
|
|---|
| 4317 | 'Patient stable. Monitoring plan established with owner.',
|
|---|
| 4318 | 'Examination revealed localised inflammation. Treatment initiated.',
|
|---|
| 4319 | 'Pre-vaccination health check completed. Patient fit for immunisation.',
|
|---|
| 4320 | 'Animal examined prior to vaccination. No contraindications found.',
|
|---|
| 4321 | 'Vaccination visit. General condition assessed; vitals normal.',
|
|---|
| 4322 | 'Patient presented for scheduled immunisation. Brief physical performed.',
|
|---|
| 4323 | 'Health status confirmed satisfactory before vaccine administration.'
|
|---|
| 4324 | ])[1 + (abs(hashtext(a.appointment_id::text || 'dsc')) % 15)] AS description,
|
|---|
| 4325 |
|
|---|
| 4326 | a.appointment_id,
|
|---|
| 4327 |
|
|---|
| 4328 | (SELECT id FROM emp_ranked
|
|---|
| 4329 | WHERE rn = (abs(hashtext(a.appointment_id::text || 'emp')) % (SELECT cnt FROM emp_count)) + 1
|
|---|
| 4330 | LIMIT 1) AS employee_id,
|
|---|
| 4331 |
|
|---|
| 4332 | (SELECT id FROM room_ranked
|
|---|
| 4333 | WHERE rn = (abs(hashtext(a.appointment_id::text || 'rom')) % (SELECT cnt FROM room_count)) + 1
|
|---|
| 4334 | LIMIT 1) AS examination_room_id
|
|---|
| 4335 |
|
|---|
| 4336 | FROM apt_sample a;
|
|---|
| 4337 |
|
|---|
| 4338 |
|
|---|
| 4339 | -- ============================================================
|
|---|
| 4340 | -- TREATMENT — one per completed examination
|
|---|
| 4341 | -- 75% prescription / 15% vaccination / 7% consultation / 3% operation
|
|---|
| 4342 | -- ~576,000 completed exams - ~432,000 prescriptions
|
|---|
| 4343 | -- ============================================================
|
|---|
| 4344 |
|
|---|
| 4345 | INSERT INTO treatment (date_treatment, notes, treatment_type_id, examination_id)
|
|---|
| 4346 | WITH type_ids AS (
|
|---|
| 4347 | SELECT
|
|---|
| 4348 | (SELECT id FROM treatment_type WHERE name = 'prescription') AS presc_id,
|
|---|
| 4349 | (SELECT id FROM treatment_type WHERE name = 'vaccination') AS vacc_id,
|
|---|
| 4350 | (SELECT id FROM treatment_type WHERE name = 'consultation') AS cons_id,
|
|---|
| 4351 | (SELECT id FROM treatment_type WHERE name = 'operation') AS oper_id
|
|---|
| 4352 | )
|
|---|
| 4353 | SELECT
|
|---|
| 4354 | (e.date_examination + (abs(hashtext(e.id::text || 'tdate')) % 4))::date AS date_treatment,
|
|---|
| 4355 |
|
|---|
| 4356 | CASE (abs(hashtext(e.id::text || 'ttype')) % 100)
|
|---|
| 4357 | -- 75% prescription (0-74)
|
|---|
| 4358 | WHEN 0 THEN 'Prescription issued following clinical assessment.'
|
|---|
| 4359 | WHEN 1 THEN 'Medication course prescribed; owner counselled on administration.'
|
|---|
| 4360 | WHEN 2 THEN 'Short course of antibiotics prescribed pending culture results.'
|
|---|
| 4361 | WHEN 3 THEN 'Anti-inflammatory therapy initiated; re-check in 10 days.'
|
|---|
| 4362 | WHEN 4 THEN 'Antiparasitic treatment prescribed; environmental treatment advised.'
|
|---|
| 4363 | WHEN 5 THEN 'Analgesic course prescribed for post-operative pain management.'
|
|---|
| 4364 | WHEN 6 THEN 'Antifungal therapy prescribed; reassess in 3 weeks.'
|
|---|
| 4365 | WHEN 7 THEN 'Prescription provided; monitor for adverse reactions.'
|
|---|
| 4366 | WHEN 8 THEN 'Combination therapy prescribed; owner given written instructions.'
|
|---|
| 4367 | WHEN 9 THEN 'Medication adjusted based on current clinical findings.'
|
|---|
| 4368 | -- 15% vaccination (75-89)
|
|---|
| 4369 | WHEN 75 THEN 'Core vaccine administered. No immediate adverse reaction observed.'
|
|---|
| 4370 | WHEN 76 THEN 'Booster vaccination given. Owner advised to monitor for 24 hours.'
|
|---|
| 4371 | WHEN 77 THEN 'Rabies vaccine administered. Certificate issued.'
|
|---|
| 4372 | WHEN 78 THEN 'Annual booster completed. Patient tolerated injection well.'
|
|---|
| 4373 | WHEN 79 THEN 'Catch-up vaccination completed. Full schedule now up to date.'
|
|---|
| 4374 | -- 7% consultation (90-96)
|
|---|
| 4375 | WHEN 90 THEN 'Owner counselled on diet and weight management.'
|
|---|
| 4376 | WHEN 91 THEN 'Behavioural concerns discussed; referral considered.'
|
|---|
| 4377 | WHEN 92 THEN 'Discussed long-term management of chronic condition.'
|
|---|
| 4378 | -- 3% operation (97-99)
|
|---|
| 4379 | WHEN 97 THEN 'Surgery performed without complications.'
|
|---|
| 4380 | WHEN 98 THEN 'Procedure completed; patient recovering well.'
|
|---|
| 4381 | WHEN 99 THEN 'Operation successful; post-op care instructions given.'
|
|---|
| 4382 | -- fill remaining slots to cover all 100 values
|
|---|
| 4383 | ELSE
|
|---|
| 4384 | CASE (abs(hashtext(e.id::text || 'ttype')) % 100)
|
|---|
| 4385 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) THEN
|
|---|
| 4386 | CASE
|
|---|
| 4387 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 75
|
|---|
| 4388 | THEN 'Prescription reissued; owner reported good compliance.'
|
|---|
| 4389 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 90
|
|---|
| 4390 | THEN 'Intranasal Bordetella vaccine administered without complication.'
|
|---|
| 4391 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 97
|
|---|
| 4392 | THEN 'Follow-up plan agreed; owner given written summary.'
|
|---|
| 4393 | ELSE 'Patient stable post-operatively; monitoring ongoing.'
|
|---|
| 4394 | END
|
|---|
| 4395 | END
|
|---|
| 4396 | END AS notes,
|
|---|
| 4397 |
|
|---|
| 4398 | CASE
|
|---|
| 4399 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 75
|
|---|
| 4400 | THEN (SELECT presc_id FROM type_ids)
|
|---|
| 4401 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 90
|
|---|
| 4402 | THEN (SELECT vacc_id FROM type_ids)
|
|---|
| 4403 | WHEN (abs(hashtext(e.id::text || 'ttype')) % 100) < 97
|
|---|
| 4404 | THEN (SELECT cons_id FROM type_ids)
|
|---|
| 4405 | ELSE (SELECT oper_id FROM type_ids)
|
|---|
| 4406 | END AS treatment_type_id,
|
|---|
| 4407 |
|
|---|
| 4408 | e.id AS examination_id
|
|---|
| 4409 |
|
|---|
| 4410 | FROM examination e
|
|---|
| 4411 | WHERE e.status = 'completed';
|
|---|
| 4412 |
|
|---|
| 4413 |
|
|---|
| 4414 | -- ============================================================
|
|---|
| 4415 | -- TREATMENT_ATTRIBUTE_VALUE
|
|---|
| 4416 | -- ~576k treatments × avg 8 attrs = ~4.6M rows
|
|---|
| 4417 | -- ============================================================
|
|---|
| 4418 |
|
|---|
| 4419 | -- PRESCRIPTION
|
|---|
| 4420 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 4421 | SELECT final_val.val, NULL, a.id, t.id
|
|---|
| 4422 | FROM treatment t
|
|---|
| 4423 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'prescription'
|
|---|
| 4424 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 4425 | CROSS JOIN LATERAL (
|
|---|
| 4426 | SELECT
|
|---|
| 4427 | (ARRAY['Antibiotic','NSAID','Corticosteroid','Antiparasitic',
|
|---|
| 4428 | 'Antifungal','Analgesic','Anticonvulsant','Cardiac',
|
|---|
| 4429 | 'Gastrointestinal','Immunosuppressant'])
|
|---|
| 4430 | [1 + (abs(hashtext(t.id::text || 'cls')) % 10)] AS medication_class,
|
|---|
| 4431 | (ARRAY['Oral','Subcutaneous injection','Intramuscular injection',
|
|---|
| 4432 | 'Topical','Intravenous','Ophthalmic'])
|
|---|
| 4433 | [1 + (abs(hashtext(t.id::text || 'rte')) % 6)] AS route,
|
|---|
| 4434 | (ARRAY['Once daily','Twice daily','Three times daily',
|
|---|
| 4435 | 'Every 48 hours','Every 72 hours','With food'])
|
|---|
| 4436 | [1 + (abs(hashtext(t.id::text || 'frq')) % 6)] AS frequency,
|
|---|
| 4437 | (7 + (abs(hashtext(t.id::text || 'dur')) % 18))::text AS duration_days,
|
|---|
| 4438 | (abs(hashtext(t.id::text || 'ref')) % 3)::text AS refills_allowed,
|
|---|
| 4439 | CASE (abs(hashtext(t.id::text || 'wth')) % 3)
|
|---|
| 4440 | WHEN 0 THEN 'None'
|
|---|
| 4441 | WHEN 1 THEN '24 hours'
|
|---|
| 4442 | ELSE '48 hours'
|
|---|
| 4443 | END AS withdrawal_period
|
|---|
| 4444 | ) v
|
|---|
| 4445 | CROSS JOIN LATERAL (
|
|---|
| 4446 | SELECT CASE a.name
|
|---|
| 4447 | WHEN 'medication_class' THEN v.medication_class
|
|---|
| 4448 | WHEN 'route' THEN v.route
|
|---|
| 4449 | WHEN 'frequency' THEN v.frequency
|
|---|
| 4450 | WHEN 'duration_days' THEN v.duration_days
|
|---|
| 4451 | WHEN 'refills_allowed' THEN v.refills_allowed
|
|---|
| 4452 | WHEN 'withdrawal_period' THEN v.withdrawal_period
|
|---|
| 4453 | END AS val
|
|---|
| 4454 | ) final_val
|
|---|
| 4455 | WHERE final_val.val IS NOT NULL;
|
|---|
| 4456 |
|
|---|
| 4457 | -- VACCINATION
|
|---|
| 4458 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 4459 | SELECT final_val.val, NULL, a.id, t.id
|
|---|
| 4460 | FROM treatment t
|
|---|
| 4461 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'vaccination'
|
|---|
| 4462 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 4463 | CROSS JOIN LATERAL (
|
|---|
| 4464 | SELECT
|
|---|
| 4465 | (ARRAY['Nobivac DHPPi','Nobivac Rabies','Feligen CRP',
|
|---|
| 4466 | 'Purevax RCPCh','Versican Plus DHPPi/L4','Canigen L4',
|
|---|
| 4467 | 'Nobivac Lepto 4','Eurican Herpes 205',
|
|---|
| 4468 | 'Felocell CVR','Quantum Cat 7'])
|
|---|
| 4469 | [1 + (abs(hashtext(t.id::text || 'vac')) % 10)] AS vaccine_name,
|
|---|
| 4470 | (ARRAY['Zoetis','MSD Animal Health','Boehringer Ingelheim','Virbac','Elanco'])
|
|---|
| 4471 | [1 + (abs(hashtext(t.id::text || 'mfr')) % 5)] AS manufacturer,
|
|---|
| 4472 | 'BN-' || lpad((abs(hashtext(t.id::text || 'bn')) % 900000 + 100000)::text, 6, '0')
|
|---|
| 4473 | AS batch_number,
|
|---|
| 4474 | CASE (abs(hashtext(t.id::text || 'nd')) % 3)
|
|---|
| 4475 | WHEN 0 THEN '1' WHEN 1 THEN '2' ELSE '3'
|
|---|
| 4476 | END AS num_doses,
|
|---|
| 4477 | CASE (abs(hashtext(t.id::text || 'dn')) % 2)
|
|---|
| 4478 | WHEN 0 THEN '1' ELSE '2'
|
|---|
| 4479 | END AS dose_number,
|
|---|
| 4480 | (ARRAY['Subcutaneous','Intramuscular','Intranasal'])
|
|---|
| 4481 | [1 + (abs(hashtext(t.id::text || 'rt2')) % 3)] AS route,
|
|---|
| 4482 | (ARRAY['Right scruff','Left scruff','Right hindlimb','Left hindlimb'])
|
|---|
| 4483 | [1 + (abs(hashtext(t.id::text || 'ste')) % 4)] AS site,
|
|---|
| 4484 | (t.date_treatment + interval '1 year')::date::text AS date_next,
|
|---|
| 4485 | CASE WHEN (abs(hashtext(t.id::text || 'adv')) % 100) < 3
|
|---|
| 4486 | THEN 'true' ELSE 'false'
|
|---|
| 4487 | END AS adverse_reaction
|
|---|
| 4488 | ) v
|
|---|
| 4489 | CROSS JOIN LATERAL (
|
|---|
| 4490 | SELECT CASE a.name
|
|---|
| 4491 | WHEN 'vaccine_name' THEN v.vaccine_name
|
|---|
| 4492 | WHEN 'manufacturer' THEN v.manufacturer
|
|---|
| 4493 | WHEN 'batch_number' THEN v.batch_number
|
|---|
| 4494 | WHEN 'num_doses' THEN v.num_doses
|
|---|
| 4495 | WHEN 'dose_number' THEN v.dose_number
|
|---|
| 4496 | WHEN 'route' THEN v.route
|
|---|
| 4497 | WHEN 'site' THEN v.site
|
|---|
| 4498 | WHEN 'date_next' THEN v.date_next
|
|---|
| 4499 | WHEN 'adverse_reaction' THEN v.adverse_reaction
|
|---|
| 4500 | END AS val
|
|---|
| 4501 | ) final_val
|
|---|
| 4502 | WHERE final_val.val IS NOT NULL;
|
|---|
| 4503 |
|
|---|
| 4504 | -- CONSULTATION
|
|---|
| 4505 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 4506 | SELECT final_val.val, NULL, a.id, t.id
|
|---|
| 4507 | FROM treatment t
|
|---|
| 4508 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'consultation'
|
|---|
| 4509 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 4510 | CROSS JOIN LATERAL (
|
|---|
| 4511 | SELECT
|
|---|
| 4512 | (ARRAY[
|
|---|
| 4513 | 'Nutrition and weight management','Behavioural assessment',
|
|---|
| 4514 | 'Chronic disease management','Pre-surgical counselling',
|
|---|
| 4515 | 'Post-operative care planning','Dental hygiene advice',
|
|---|
| 4516 | 'Parasite prevention review','Vaccination schedule planning',
|
|---|
| 4517 | 'End-of-life care discussion','Second opinion review'
|
|---|
| 4518 | ])[1 + (abs(hashtext(t.id::text || 'top')) % 10)] AS topic,
|
|---|
| 4519 | (ARRAY[
|
|---|
| 4520 | 'Owner presented concerns regarding the pet''s appetite and energy levels. A full dietary review was completed and a lower-calorie prescription diet was recommended. Owner was shown how to measure portions correctly and advised to recheck in 4 weeks.',
|
|---|
| 4521 | 'Behavioural history taken in detail. Pet displays anxiety-related signs including excessive grooming and vocalization. Environmental enrichment strategies discussed and a referral to a veterinary behaviourist was considered.',
|
|---|
| 4522 | 'Long-term management plan for the pet''s diagnosed chronic kidney disease was reviewed. Blood results interpreted and ACE inhibitor dosage adjusted. Owner counselled on signs of deterioration.',
|
|---|
| 4523 | 'Pre-surgical consultation completed for elective spay procedure. Risks and benefits of anaesthesia explained. Pre-operative blood panel ordered. Owner provided written consent and fasting instructions.',
|
|---|
| 4524 | 'Post-operative wound checked and healing progress assessed. Owner demonstrated correct application of topical antiseptic. Suture removal booked for 10 days post-op.',
|
|---|
| 4525 | 'Dental examination findings discussed with owner. Stage 2 periodontal disease identified. Professional scale and polish recommended. Home brushing technique demonstrated.',
|
|---|
| 4526 | 'Current parasite prevention programme assessed. Updated protocol prescribed combining monthly spot-on and quarterly wormer. Environmental hygiene advice given.',
|
|---|
| 4527 | 'Full vaccination history reviewed. Pet was overdue for core and leptospirosis boosters. Schedule re-established and owner reminded of annual requirement.',
|
|---|
| 4528 | 'Compassionate discussion held with owner regarding quality of life for their senior pet with advanced neoplasia. Palliative care options outlined.',
|
|---|
| 4529 | 'Second opinion consultation for recurrent skin condition. Differential diagnoses reconsidered; skin biopsy recommended to rule out immune-mediated disease.'
|
|---|
| 4530 | ])[1 + (abs(hashtext(t.id::text || 'dsc')) % 10)] AS description,
|
|---|
| 4531 | CASE WHEN (abs(hashtext(t.id::text || 'ref')) % 100) < 15
|
|---|
| 4532 | THEN 'true' ELSE 'false'
|
|---|
| 4533 | END AS referral,
|
|---|
| 4534 | CASE WHEN (abs(hashtext(t.id::text || 'ref')) % 100) < 15
|
|---|
| 4535 | THEN (ARRAY['Veterinary Dermatologist','Veterinary Cardiologist',
|
|---|
| 4536 | 'Veterinary Behaviourist','Veterinary Oncologist',
|
|---|
| 4537 | 'Veterinary Ophthalmologist','Veterinary Neurologist'])
|
|---|
| 4538 | [1 + (abs(hashtext(t.id::text || 'rto')) % 6)]
|
|---|
| 4539 | ELSE NULL
|
|---|
| 4540 | END AS referral_to,
|
|---|
| 4541 | (ARRAY['7','14','21','30'])
|
|---|
| 4542 | [1 + (abs(hashtext(t.id::text || 'fup')) % 4)] AS follow_up_days,
|
|---|
| 4543 | CASE WHEN (abs(hashtext(t.id::text || 'own')) % 10) < 9
|
|---|
| 4544 | THEN 'true' ELSE 'false'
|
|---|
| 4545 | END AS owner_present
|
|---|
| 4546 | ) v
|
|---|
| 4547 | CROSS JOIN LATERAL (
|
|---|
| 4548 | SELECT CASE a.name
|
|---|
| 4549 | WHEN 'topic' THEN v.topic
|
|---|
| 4550 | WHEN 'description' THEN v.description
|
|---|
| 4551 | WHEN 'referral' THEN v.referral
|
|---|
| 4552 | WHEN 'referral_to' THEN v.referral_to
|
|---|
| 4553 | WHEN 'follow_up_days' THEN v.follow_up_days
|
|---|
| 4554 | WHEN 'owner_present' THEN v.owner_present
|
|---|
| 4555 | END AS val
|
|---|
| 4556 | ) final_val
|
|---|
| 4557 | WHERE final_val.val IS NOT NULL;
|
|---|
| 4558 |
|
|---|
| 4559 | -- OPERATION
|
|---|
| 4560 | INSERT INTO treatment_attribute_value (value, notes, treatment_attribute_id, treatment_id)
|
|---|
| 4561 | SELECT final_val.val, NULL, a.id, t.id
|
|---|
| 4562 | FROM treatment t
|
|---|
| 4563 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'operation'
|
|---|
| 4564 | JOIN treatment_attribute a ON a.treatment_type_id = tt.id
|
|---|
| 4565 | CROSS JOIN LATERAL (
|
|---|
| 4566 | SELECT
|
|---|
| 4567 | (ARRAY[
|
|---|
| 4568 | 'Ovariohysterectomy (spay)','Orchiectomy (neuter)',
|
|---|
| 4569 | 'Mass / tumour excision','Fracture repair (ORIF)',
|
|---|
| 4570 | 'Intestinal foreign body removal',
|
|---|
| 4571 | 'Cystotomy (bladder stone removal)','Gastropexy',
|
|---|
| 4572 | 'Enucleation','Amputation','Caesarean section',
|
|---|
| 4573 | 'Exploratory laparotomy','Cruciate ligament repair (TPLO)',
|
|---|
| 4574 | 'Dental extraction','Wound debridement and closure',
|
|---|
| 4575 | 'Thoracostomy tube placement'
|
|---|
| 4576 | ])[1 + (abs(hashtext(t.id::text || 'opt')) % 15)] AS operation_type,
|
|---|
| 4577 | (ARRAY['Successful','Successful','Successful','Successful',
|
|---|
| 4578 | 'Complicated','Unsuccessful'])
|
|---|
| 4579 | [1 + (abs(hashtext(t.id::text || 'sts')) % 6)] AS status,
|
|---|
| 4580 | (ARRAY[
|
|---|
| 4581 | 'Propofol induction / Isoflurane maintenance',
|
|---|
| 4582 | 'Alfaxalone induction / Isoflurane maintenance',
|
|---|
| 4583 | 'Ketamine-Midazolam / Isoflurane maintenance',
|
|---|
| 4584 | 'Propofol TIVA',
|
|---|
| 4585 | 'Medetomidine-Butorphanol sedation (minor procedure)'
|
|---|
| 4586 | ])[1 + (abs(hashtext(t.id::text || 'ans')) % 5)] AS anesthesia,
|
|---|
| 4587 | (15 + (abs(hashtext(t.id::text || 'dur')) % 166))::text AS duration_minutes,
|
|---|
| 4588 | (t.date_treatment + (7 + abs(hashtext(t.id::text || 'chk')) % 8))::text
|
|---|
| 4589 | AS date_checkup,
|
|---|
| 4590 | (SELECT e.first_name || ' ' || e.last_name
|
|---|
| 4591 | FROM employee e
|
|---|
| 4592 | WHERE e.role_id = 2
|
|---|
| 4593 | ORDER BY abs(hashtext(t.id::text || 'srg' || e.id::text))
|
|---|
| 4594 | LIMIT 1) AS surgeon,
|
|---|
| 4595 | CASE WHEN (abs(hashtext(t.id::text || 'cmp')) % 100) < 12
|
|---|
| 4596 | THEN 'true' ELSE 'false'
|
|---|
| 4597 | END AS complications
|
|---|
| 4598 | ) v
|
|---|
| 4599 | CROSS JOIN LATERAL (
|
|---|
| 4600 | SELECT CASE a.name
|
|---|
| 4601 | WHEN 'operation_type' THEN v.operation_type
|
|---|
| 4602 | WHEN 'status' THEN v.status
|
|---|
| 4603 | WHEN 'anesthesia' THEN v.anesthesia
|
|---|
| 4604 | WHEN 'duration_minutes' THEN v.duration_minutes
|
|---|
| 4605 | WHEN 'date_checkup' THEN v.date_checkup
|
|---|
| 4606 | WHEN 'surgeon' THEN v.surgeon
|
|---|
| 4607 | WHEN 'complications' THEN v.complications
|
|---|
| 4608 | END AS val
|
|---|
| 4609 | ) final_val
|
|---|
| 4610 | WHERE final_val.val IS NOT NULL;
|
|---|
| 4611 |
|
|---|
| 4612 |
|
|---|
| 4613 | -- ============================================================
|
|---|
| 4614 | -- PRESCRIPTION — one per completed examination
|
|---|
| 4615 | -- with a prescription treatment (~432,000 rows)
|
|---|
| 4616 | -- ============================================================
|
|---|
| 4617 |
|
|---|
| 4618 | INSERT INTO prescription (examination_id, date_start, date_end, description)
|
|---|
| 4619 | SELECT
|
|---|
| 4620 | e.id AS examination_id,
|
|---|
| 4621 | e.date_examination AS date_start,
|
|---|
| 4622 | (e.date_examination + (7 + abs(hashtext(e.id::text || 'pend')) % 21))::date AS date_end,
|
|---|
| 4623 | (ARRAY[
|
|---|
| 4624 | 'Administer as directed. Complete the full course.',
|
|---|
| 4625 | 'Give with food to reduce gastric upset.',
|
|---|
| 4626 | 'Monitor for adverse reactions; contact clinic if vomiting occurs.',
|
|---|
| 4627 | 'Store in a cool dry place. Keep out of reach of children.',
|
|---|
| 4628 | 'Re-examine if no improvement within 5 days.',
|
|---|
| 4629 | 'Do not crush tablets; administer whole.',
|
|---|
| 4630 | 'Shake oral suspension well before each use.',
|
|---|
| 4631 | 'Continue until finished even if pet appears better.',
|
|---|
| 4632 | 'Avoid direct sunlight on treated area.',
|
|---|
| 4633 | 'Return for recheck at end of course.'
|
|---|
| 4634 | ])[1 + (abs(hashtext(e.id::text || 'pdsc')) % 10)] AS description
|
|---|
| 4635 | FROM examination e
|
|---|
| 4636 | JOIN treatment t ON t.examination_id = e.id
|
|---|
| 4637 | JOIN treatment_type tt ON tt.id = t.treatment_type_id AND tt.name = 'prescription'
|
|---|
| 4638 | WHERE e.status = 'completed'
|
|---|
| 4639 | ON CONFLICT (examination_id) DO NOTHING;
|
|---|
| 4640 |
|
|---|
| 4641 |
|
|---|
| 4642 | -- ============================================================
|
|---|
| 4643 | -- PRESCRIPTION_MEDICINE — target ~10M rows
|
|---|
| 4644 | -- ~432,000 prescriptions × avg 25 medicines = ~10.8M
|
|---|
| 4645 | -- generate_series 1-30, want_count 20-30
|
|---|
| 4646 | -- ============================================================
|
|---|
| 4647 |
|
|---|
| 4648 | WITH med_ranked AS (
|
|---|
| 4649 | SELECT id, row_number() OVER (ORDER BY id) AS rn
|
|---|
| 4650 | FROM medicine
|
|---|
| 4651 | ),
|
|---|
| 4652 | med_count AS (
|
|---|
| 4653 | SELECT count(*) AS total FROM medicine
|
|---|
| 4654 | ),
|
|---|
| 4655 | slots AS (
|
|---|
| 4656 | SELECT
|
|---|
| 4657 | p.id AS prescription_id,
|
|---|
| 4658 | gs.slot
|
|---|
| 4659 | FROM prescription p
|
|---|
| 4660 | CROSS JOIN generate_series(1, 30) AS gs(slot)
|
|---|
| 4661 | ),
|
|---|
| 4662 | assigned AS (
|
|---|
| 4663 | SELECT
|
|---|
| 4664 | s.prescription_id,
|
|---|
| 4665 | s.slot,
|
|---|
| 4666 | mr.id AS medicine_id,
|
|---|
| 4667 | 1 + (abs(hashtext(s.prescription_id::text || '-dos-' || s.slot::text)) % 3) AS dosage,
|
|---|
| 4668 | 3 + (abs(hashtext(s.prescription_id::text || '-day-' || s.slot::text)) % 26) AS num_days,
|
|---|
| 4669 | -- each prescription wants between 20 and 30 medicines
|
|---|
| 4670 | 20 + (abs(hashtext(s.prescription_id::text || '-cnt')) % 11) AS want_count
|
|---|
| 4671 | FROM slots s
|
|---|
| 4672 | CROSS JOIN med_count mc
|
|---|
| 4673 | JOIN med_ranked mr
|
|---|
| 4674 | ON mr.rn = (abs(hashtext(s.prescription_id::text || '-med-' || s.slot::text)) % mc.total) + 1
|
|---|
| 4675 | ),
|
|---|
| 4676 | filtered AS (
|
|---|
| 4677 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 4678 | FROM assigned
|
|---|
| 4679 | WHERE slot <= want_count
|
|---|
| 4680 | ),
|
|---|
| 4681 | deduped AS (
|
|---|
| 4682 | SELECT DISTINCT ON (prescription_id, medicine_id)
|
|---|
| 4683 | prescription_id, medicine_id, dosage, num_days
|
|---|
| 4684 | FROM filtered
|
|---|
| 4685 | ORDER BY prescription_id, medicine_id
|
|---|
| 4686 | )
|
|---|
| 4687 | INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
|
|---|
| 4688 | SELECT prescription_id, medicine_id, dosage, num_days
|
|---|
| 4689 | FROM deduped
|
|---|
| 4690 | ON CONFLICT (prescription_id, medicine_id) DO NOTHING;
|
|---|
| 4691 |
|
|---|
| 4692 |
|
|---|
| 4693 | -- SELECT count(*) FROM appointment;
|
|---|
| 4694 | -- SELECT * FROM appointment;
|
|---|
| 4695 | -- SELECT count(*) FROM examination;
|
|---|
| 4696 | -- SELECT * FROM examination;
|
|---|
| 4697 | -- SELECT count(*) FROM treatment;
|
|---|
| 4698 | -- SELECT * FROM treatment;
|
|---|
| 4699 | -- SELECT count(*) FROM treatment_attribute_value;
|
|---|
| 4700 | -- SELECT * FROM treatment_attribute_value;
|
|---|
| 4701 | -- SELECT count(*) FROM prescription;
|
|---|
| 4702 | -- SELECT * FROM prescription;
|
|---|
| 4703 | -- SELECT count(*) FROM prescription_medicine;
|
|---|
| 4704 | --
|
|---|
| 4705 | -- SELECT pg_size_pretty(pg_database_size(current_database()));
|
|---|
| 4706 |
|
|---|
| 4707 |
|
|---|
| 4708 | -- ============================================================
|
|---|
| 4709 | -- discount
|
|---|
| 4710 | -- ~25% of shop items currently carry an active promotional discount
|
|---|
| 4711 | -- ============================================================
|
|---|
| 4712 |
|
|---|
| 4713 | INSERT INTO discount (type, value, description, date_from, date_to, shop_item_id)
|
|---|
| 4714 | SELECT
|
|---|
| 4715 | CASE
|
|---|
| 4716 | WHEN (abs(hashtext(si.id::text || 'dtype')) % 2) = 0
|
|---|
| 4717 | THEN 'fixed'
|
|---|
| 4718 | ELSE 'percentage'
|
|---|
| 4719 | END AS type,
|
|---|
| 4720 |
|
|---|
| 4721 | CASE
|
|---|
| 4722 | WHEN (abs(hashtext(si.id::text || 'dtype')) % 2) = 0
|
|---|
| 4723 | THEN round(
|
|---|
| 4724 | (1 + (abs(hashtext(si.id::text || 'dval')) % 1500) / 100.0)::numeric,
|
|---|
| 4725 | 2
|
|---|
| 4726 | )
|
|---|
| 4727 | ELSE round(
|
|---|
| 4728 | (5 + (abs(hashtext(si.id::text || 'dval')) % 3500) / 100.0)::numeric,
|
|---|
| 4729 | 2
|
|---|
| 4730 | )
|
|---|
| 4731 | END AS value,
|
|---|
| 4732 |
|
|---|
| 4733 | (ARRAY[
|
|---|
| 4734 | 'Seasonal promotion',
|
|---|
| 4735 | 'Clearance discount',
|
|---|
| 4736 | 'Loyalty customer discount',
|
|---|
| 4737 | 'Bulk purchase discount',
|
|---|
| 4738 | 'New product launch offer',
|
|---|
| 4739 | 'Holiday special',
|
|---|
| 4740 | 'Overstock clearance',
|
|---|
| 4741 | 'Limited time offer',
|
|---|
| 4742 | 'Member exclusive discount',
|
|---|
| 4743 | 'Weekend flash sale'
|
|---|
| 4744 | ])[1 + (abs(hashtext(si.id::text || 'ddsc')) % 10)] AS description,
|
|---|
| 4745 |
|
|---|
| 4746 | CURRENT_DATE - (abs(hashtext(si.id::text || 'dfrom')) % 30) AS date_from,
|
|---|
| 4747 |
|
|---|
| 4748 | CURRENT_DATE + (abs(hashtext(si.id::text || 'dto')) % 60 + 1) AS date_to,
|
|---|
| 4749 |
|
|---|
| 4750 | si.id AS shop_item_id
|
|---|
| 4751 |
|
|---|
| 4752 | FROM shop_item si
|
|---|
| 4753 | WHERE (abs(hashtext(si.id::text || 'dpick')) % 100) < 25;
|
|---|
| 4754 |
|
|---|
| 4755 | ALTER TABLE invoice_item DISABLE TRIGGER trg_generate_num_item;
|
|---|
| 4756 |
|
|---|
| 4757 | -- ============================================================
|
|---|
| 4758 | -- invoice + invoice_item — clinical visits
|
|---|
| 4759 | -- One invoice per completed examination that has at least one
|
|---|
| 4760 | -- treatment; each treatment becomes its own invoice_item line.
|
|---|
| 4761 | -- ~15% of invoices redeem an active coupon.
|
|---|
| 4762 | -- ============================================================
|
|---|
| 4763 |
|
|---|
| 4764 | WITH billable_examinations AS (
|
|---|
| 4765 | SELECT
|
|---|
| 4766 | e.id AS examination_id,
|
|---|
| 4767 | e.date_examination,
|
|---|
| 4768 | a.owner_id
|
|---|
| 4769 | FROM examination e
|
|---|
| 4770 | JOIN appointment a ON a.id = e.appointment_id
|
|---|
| 4771 | WHERE e.status = 'completed'
|
|---|
| 4772 | AND EXISTS (SELECT 1 FROM treatment t WHERE t.examination_id = e.id)
|
|---|
| 4773 | ),
|
|---|
| 4774 |
|
|---|
| 4775 | invoice_src AS (
|
|---|
| 4776 | SELECT
|
|---|
| 4777 | nextval(pg_get_serial_sequence('invoice', 'id')) AS invoice_id,
|
|---|
| 4778 | be.examination_id,
|
|---|
| 4779 | be.date_examination AS date_invoice,
|
|---|
| 4780 | be.owner_id,
|
|---|
| 4781 | CASE WHEN (abs(hashtext(be.examination_id::text || 'cpn')) % 100) < 15
|
|---|
| 4782 | THEN (
|
|---|
| 4783 | SELECT c.id FROM coupon c
|
|---|
| 4784 | WHERE c.is_active = true
|
|---|
| 4785 | ORDER BY abs(hashtext(be.examination_id::text || 'cpnpick' || c.id::text))
|
|---|
| 4786 | LIMIT 1
|
|---|
| 4787 | )
|
|---|
| 4788 | ELSE NULL
|
|---|
| 4789 | END AS coupon_id
|
|---|
| 4790 | FROM billable_examinations be
|
|---|
| 4791 | ),
|
|---|
| 4792 |
|
|---|
| 4793 | new_invoices AS (
|
|---|
| 4794 | INSERT INTO invoice (id, date_invoice, total, coupon_id, owner_id)
|
|---|
| 4795 | SELECT invoice_id, date_invoice, 0.00, coupon_id, owner_id
|
|---|
| 4796 | FROM invoice_src
|
|---|
| 4797 | RETURNING id
|
|---|
| 4798 | ),
|
|---|
| 4799 |
|
|---|
| 4800 | invoice_lines AS (
|
|---|
| 4801 | SELECT
|
|---|
| 4802 | isrc.invoice_id,
|
|---|
| 4803 | t.id AS treatment_id,
|
|---|
| 4804 | CASE tt.name
|
|---|
| 4805 | WHEN 'prescription' THEN round((15 + random() * 60)::numeric, 2)
|
|---|
| 4806 | WHEN 'vaccination' THEN round((20 + random() * 30)::numeric, 2)
|
|---|
| 4807 | WHEN 'consultation' THEN round((25 + random() * 45)::numeric, 2)
|
|---|
| 4808 | WHEN 'operation' THEN round((150 + random() * 850)::numeric, 2)
|
|---|
| 4809 | END AS price
|
|---|
| 4810 | FROM invoice_src isrc
|
|---|
| 4811 | JOIN treatment t ON t.examination_id = isrc.examination_id
|
|---|
| 4812 | JOIN treatment_type tt ON tt.id = t.treatment_type_id
|
|---|
| 4813 | )
|
|---|
| 4814 |
|
|---|
| 4815 | INSERT INTO invoice_item (num_item, invoice_id, price, quantity, type, treatment_id)
|
|---|
| 4816 | SELECT
|
|---|
| 4817 | row_number() OVER (PARTITION BY invoice_id ORDER BY treatment_id) AS num_item,
|
|---|
| 4818 | invoice_id,
|
|---|
| 4819 | price,
|
|---|
| 4820 | 1 AS quantity,
|
|---|
| 4821 | 'treatment' AS type,
|
|---|
| 4822 | treatment_id
|
|---|
| 4823 | FROM invoice_lines;
|
|---|
| 4824 |
|
|---|
| 4825 | -- ============================================================
|
|---|
| 4826 | -- invoice + invoice_item — retail purchases (bulk)
|
|---|
| 4827 | -- 200,000 standalone shop invoices spread across all owners
|
|---|
| 4828 | -- over the last 3 years, each with 5-15 line items
|
|---|
| 4829 | -- ============================================================
|
|---|
| 4830 |
|
|---|
| 4831 | WITH owner_count AS (
|
|---|
| 4832 | SELECT count(*) AS cnt FROM owner
|
|---|
| 4833 | ),
|
|---|
| 4834 |
|
|---|
| 4835 | owner_ranked AS (
|
|---|
| 4836 | SELECT id, row_number() OVER (ORDER BY id) AS rn FROM owner
|
|---|
| 4837 | ),
|
|---|
| 4838 |
|
|---|
| 4839 | invoice_src AS (
|
|---|
| 4840 | SELECT
|
|---|
| 4841 | nextval(pg_get_serial_sequence('invoice', 'id')) AS invoice_id,
|
|---|
| 4842 | o.id AS owner_id,
|
|---|
| 4843 | CURRENT_DATE - (abs(hashtext(gs.n::text || 'shpdate')) % 1095) AS date_invoice,
|
|---|
| 4844 | 5 + (abs(hashtext(gs.n::text || 'itemcnt')) % 11) AS num_items, -- 5-15 items
|
|---|
| 4845 | CASE WHEN (abs(hashtext(gs.n::text || 'shpcpn')) % 100) < 15
|
|---|
| 4846 | THEN (
|
|---|
| 4847 | SELECT c.id FROM coupon c
|
|---|
| 4848 | WHERE c.is_active = true
|
|---|
| 4849 | ORDER BY abs(hashtext(gs.n::text || 'shpcpnpick' || c.id::text))
|
|---|
| 4850 | LIMIT 1
|
|---|
| 4851 | )
|
|---|
| 4852 | ELSE NULL
|
|---|
| 4853 | END AS coupon_id
|
|---|
| 4854 | FROM generate_series(1, 200000) AS gs(n)
|
|---|
| 4855 | CROSS JOIN owner_count oc
|
|---|
| 4856 | JOIN owner_ranked o
|
|---|
| 4857 | ON o.rn = ((abs(hashtext(gs.n::text || 'ownerpick')) % oc.cnt) + 1)
|
|---|
| 4858 | ),
|
|---|
| 4859 |
|
|---|
| 4860 | new_invoices AS (
|
|---|
| 4861 | INSERT INTO invoice (id, date_invoice, total, coupon_id, owner_id)
|
|---|
| 4862 | SELECT invoice_id, date_invoice, 0.00, coupon_id, owner_id
|
|---|
| 4863 | FROM invoice_src
|
|---|
| 4864 | RETURNING id
|
|---|
| 4865 | ),
|
|---|
| 4866 |
|
|---|
| 4867 | item_slots AS (
|
|---|
| 4868 | SELECT isrc.invoice_id, gs.slot
|
|---|
| 4869 | FROM invoice_src isrc
|
|---|
| 4870 | CROSS JOIN generate_series(1, 15) AS gs(slot)
|
|---|
| 4871 | WHERE gs.slot <= isrc.num_items
|
|---|
| 4872 | ),
|
|---|
| 4873 |
|
|---|
| 4874 | item_count AS (
|
|---|
| 4875 | SELECT count(*) AS total FROM shop_item
|
|---|
| 4876 | ),
|
|---|
| 4877 |
|
|---|
| 4878 | item_ranked AS (
|
|---|
| 4879 | SELECT id, price, row_number() OVER (ORDER BY id) AS rn FROM shop_item
|
|---|
| 4880 | )
|
|---|
| 4881 |
|
|---|
| 4882 | INSERT INTO invoice_item (num_item, invoice_id, price, quantity, type, shop_item_id)
|
|---|
| 4883 | SELECT
|
|---|
| 4884 | isl.slot AS num_item,
|
|---|
| 4885 | isl.invoice_id,
|
|---|
| 4886 | ir.price,
|
|---|
| 4887 | 1 + (abs(hashtext(isl.invoice_id::text || 'qty' || isl.slot::text)) % 3) AS quantity,
|
|---|
| 4888 | 'shop_item' AS type,
|
|---|
| 4889 | ir.id AS shop_item_id
|
|---|
| 4890 | FROM item_slots isl
|
|---|
| 4891 | CROSS JOIN item_count ic
|
|---|
| 4892 | JOIN item_ranked ir
|
|---|
| 4893 | ON ir.rn = (abs(hashtext(isl.invoice_id::text || 'item' || isl.slot::text)) % ic.total) + 1;
|
|---|
| 4894 |
|
|---|
| 4895 |
|
|---|
| 4896 | ALTER TABLE invoice_item ENABLE TRIGGER trg_generate_num_item;
|
|---|
| 4897 |
|
|---|
| 4898 | -- ============================================================
|
|---|
| 4899 | -- invoice.total — recompute from invoice_item lines and apply
|
|---|
| 4900 | -- the redeemed coupon's discount, then bump coupon usage_count
|
|---|
| 4901 | -- ============================================================
|
|---|
| 4902 |
|
|---|
| 4903 | UPDATE coupon c
|
|---|
| 4904 | SET usage_count = LEAST(c.usage_count + sub.uses, c.usage_limit)
|
|---|
| 4905 | FROM (
|
|---|
| 4906 | SELECT coupon_id, count(*) AS uses
|
|---|
| 4907 | FROM invoice
|
|---|
| 4908 | WHERE coupon_id IS NOT NULL
|
|---|
| 4909 | GROUP BY coupon_id
|
|---|
| 4910 | ) sub
|
|---|
| 4911 | WHERE c.id = sub.coupon_id;
|
|---|
| 4912 |
|
|---|
| 4913 | WITH invoice_calc AS (
|
|---|
| 4914 | SELECT
|
|---|
| 4915 | i.id AS invoice_id,
|
|---|
| 4916 | i.coupon_id,
|
|---|
| 4917 | SUM(ii.price * ii.quantity) AS subtotal
|
|---|
| 4918 | FROM invoice i
|
|---|
| 4919 | JOIN invoice_item ii ON ii.invoice_id = i.id
|
|---|
| 4920 | GROUP BY i.id, i.coupon_id
|
|---|
| 4921 | )
|
|---|
| 4922 | UPDATE invoice i
|
|---|
| 4923 | SET total = GREATEST(
|
|---|
| 4924 | ROUND(
|
|---|
| 4925 | CASE
|
|---|
| 4926 | WHEN c.id IS NOT NULL AND ic.subtotal >= COALESCE(c.min_total, 0) THEN
|
|---|
| 4927 | CASE c.type
|
|---|
| 4928 | WHEN 'fixed' THEN ic.subtotal - c.value
|
|---|
| 4929 | WHEN 'percentage' THEN ic.subtotal * (1 - c.value / 100)
|
|---|
| 4930 | END
|
|---|
| 4931 | ELSE ic.subtotal
|
|---|
| 4932 | END,
|
|---|
| 4933 | 2),
|
|---|
| 4934 | 0.00)
|
|---|
| 4935 | FROM invoice_calc ic
|
|---|
| 4936 | LEFT JOIN coupon c ON c.id = ic.coupon_id
|
|---|
| 4937 | WHERE i.id = ic.invoice_id;
|
|---|
| 4938 |
|
|---|
| 4939 | -- ============================================================
|
|---|
| 4940 | -- payment
|
|---|
| 4941 | -- ============================================================
|
|---|
| 4942 |
|
|---|
| 4943 | INSERT INTO payment (date_payment, amount, method, invoice_id)
|
|---|
| 4944 | SELECT
|
|---|
| 4945 | i.date_invoice + (abs(hashtext(i.id::text || 'paydate')) % 6) AS date_payment,
|
|---|
| 4946 | i.total AS amount,
|
|---|
| 4947 | CASE
|
|---|
| 4948 | WHEN (abs(hashtext(i.id::text || 'paymethod')) % 100) < 30 THEN 'cash'
|
|---|
| 4949 | WHEN (abs(hashtext(i.id::text || 'paymethod')) % 100) < 55 THEN 'debit card'
|
|---|
| 4950 | WHEN (abs(hashtext(i.id::text || 'paymethod')) % 100) < 80 THEN 'credit card'
|
|---|
| 4951 | WHEN (abs(hashtext(i.id::text || 'paymethod')) % 100) < 95 THEN 'digital wallet'
|
|---|
| 4952 | ELSE 'other'
|
|---|
| 4953 | END AS method,
|
|---|
| 4954 | i.id AS invoice_id
|
|---|
| 4955 | FROM invoice i;
|
|---|
| 4956 |
|
|---|
| 4957 | -- ========================
|
|---|
| 4958 | -- Drop temporary tables
|
|---|
| 4959 | -- ========================
|
|---|
| 4960 | DROP TABLE IF EXISTS temp_addresses;
|
|---|
| 4961 | DROP TABLE IF EXISTS temp_breeds_mammal;
|
|---|
| 4962 | DROP TABLE IF EXISTS temp_breeds_bird;
|
|---|
| 4963 | DROP TABLE IF EXISTS temp_breeds_fish;
|
|---|
| 4964 | DROP TABLE IF EXISTS temp_breeds_amphibian;
|
|---|
| 4965 | DROP TABLE IF EXISTS temp_breeds_reptile;
|
|---|
| 4966 | DROP TABLE IF EXISTS temp_pet_names;
|
|---|
| 4967 | DROP TABLE IF EXISTS temp_medical_history;
|
|---|
| 4968 | DROP TABLE IF EXISTS temp_certificate_names;
|
|---|
| 4969 | DROP TABLE IF EXISTS temp_spec_data;
|
|---|
| 4970 | DROP TABLE IF EXISTS temp_prescription_advice;
|
|---|
| 4971 | DROP TABLE IF EXISTS temp_surnames;
|
|---|
| 4972 | DROP TABLE IF EXISTS temp_male_names;
|
|---|
| 4973 | DROP TABLE IF EXISTS temp_female_names;
|
|---|
| 4974 | DROP TABLE IF EXISTS temp_med1; |
|---|