[19fa1a3] | 1 | create table account(
|
---|
| 2 | id serial primary key,
|
---|
| 3 | username varchar(255) not null,
|
---|
| 4 | email varchar(255) not null,
|
---|
| 5 | password varchar(255) not null,
|
---|
| 6 | balance decimal(15, 2) not null
|
---|
| 7 | );
|
---|
| 8 |
|
---|
| 9 | create table "transaction"(
|
---|
| 10 | id serial primary key,
|
---|
| 11 | amount decimal(15, 2) not null,
|
---|
| 12 | currency varchar(255) not null,
|
---|
| 13 | type varchar(50) not null,
|
---|
| 14 | timestamp timestamp default current_timestamp,
|
---|
| 15 | account_id int not null,
|
---|
| 16 | foreign key (account_id) references account(id)
|
---|
| 17 | );
|
---|
| 18 |
|
---|
| 19 | create table transfer(
|
---|
| 20 | id serial primary key,
|
---|
| 21 | s_id int not null,
|
---|
| 22 | r_id int not null,
|
---|
| 23 | foreign key(s_id) references account(id),
|
---|
| 24 | foreign key(r_id) references
|
---|
| 25 | account(id)
|
---|
| 26 |
|
---|
| 27 | );
|
---|
| 28 |
|
---|
| 29 | create table deposit(
|
---|
| 30 | id serial primary key,
|
---|
| 31 | account_id int not null,
|
---|
| 32 | transaction_id int not null,
|
---|
| 33 | amount decimal(15,2) not null,
|
---|
| 34 | foreign key(account_id) references account(id),
|
---|
| 35 | foreign key(transaction_id) references transaction(id)
|
---|
| 36 | );
|
---|
| 37 |
|
---|
| 38 | create table withdraw(
|
---|
| 39 | id serial primary key,
|
---|
| 40 | account_id int not null,
|
---|
| 41 | transaction_id int not null,
|
---|
| 42 | amount decimal(15,2) not null,
|
---|
| 43 | foreign key(account_id) references account(id),
|
---|
| 44 | foreign key(transaction_id) references transaction(id)
|
---|
| 45 | );
|
---|
| 46 |
|
---|
| 47 | create table transferred_money(
|
---|
| 48 | id serial primary key,
|
---|
| 49 | s_account_id int not null,
|
---|
| 50 | r_account_id int not null,
|
---|
| 51 | t_id int not null,
|
---|
| 52 | currency varchar(50) not null,
|
---|
| 53 | foreign key (s_account_id) references account(id),
|
---|
| 54 | foreign key (r_account_id) references account(id),
|
---|
| 55 | foreign key (t_id) references transaction(id)
|
---|
| 56 | );
|
---|
| 57 |
|
---|
| 58 |
|
---|
| 59 | CREATE OR REPLACE FUNCTION after_transaction_trigger()
|
---|
| 60 | RETURNS TRIGGER AS $$
|
---|
| 61 | BEGIN
|
---|
| 62 | IF NEW.type = 'Deposit' THEN
|
---|
| 63 | INSERT INTO Deposit(account_id, transaction_id, amount)
|
---|
| 64 | VALUES (NEW.account_id, NEW.id, NEW.amount);
|
---|
| 65 |
|
---|
| 66 | ELSIF NEW.type = 'Withdrawal' THEN
|
---|
| 67 | INSERT INTO Withdraw(account_id, transaction_id, amount)
|
---|
| 68 | VALUES (NEW.account_id, NEW.id, NEW.amount);
|
---|
| 69 |
|
---|
| 70 | ELSIF NEW.type LIKE '(MKD) Transfer Out to%' OR
|
---|
| 71 | NEW.type LIKE '(USD) Transfer Out to%' OR
|
---|
| 72 | NEW.type LIKE '(EUR) Transfer Out to%' OR
|
---|
| 73 | NEW.type LIKE '(GBP) Transfer Out to%' THEN
|
---|
| 74 | INSERT INTO transferred_money(s_account_id, r_account_id, t_id, currency)
|
---|
| 75 | SELECT NEW.account_id,
|
---|
| 76 | (SELECT id FROM account
|
---|
| 77 | WHERE username = TRIM(SUBSTRING(NEW.type FROM POSITION('Transfer Out to ' IN NEW.type) + 15))
|
---|
| 78 | LIMIT 1),
|
---|
| 79 | NEW.id, NEW.currency;
|
---|
| 80 | END IF;
|
---|
| 81 |
|
---|
| 82 | RETURN NEW;
|
---|
| 83 | END;
|
---|
| 84 | $$ LANGUAGE plpgsql;
|
---|
| 85 |
|
---|
| 86 |
|
---|
| 87 |
|
---|
| 88 | CREATE TRIGGER after_transaction
|
---|
| 89 | AFTER INSERT ON transaction
|
---|
| 90 | FOR EACH ROW
|
---|
| 91 | EXECUTE FUNCTION after_transaction_trigger();
|
---|
| 92 |
|
---|
| 93 |
|
---|
| 94 |
|
---|
| 95 | CREATE OR REPLACE FUNCTION after_transaction_trigger2()
|
---|
| 96 | RETURNS TRIGGER AS $$
|
---|
| 97 | BEGIN
|
---|
| 98 | IF NEW.type = 'Deposit' THEN
|
---|
| 99 | -- Log deposit as a self-transfer
|
---|
| 100 | INSERT INTO transfer(s_id, r_id)
|
---|
| 101 | VALUES (NEW.account_id, NEW.account_id);
|
---|
| 102 |
|
---|
| 103 | ELSIF NEW.type = 'Withdrawal' THEN
|
---|
| 104 | -- Log withdrawal as a self-transfer
|
---|
| 105 | INSERT INTO transfer(s_id, r_id)
|
---|
| 106 | VALUES (NEW.account_id, NEW.account_id);
|
---|
| 107 |
|
---|
| 108 | ELSIF NEW.type LIKE '(MKD) Transfer Out to%' OR
|
---|
| 109 | NEW.type LIKE '(USD) Transfer Out to%' OR
|
---|
| 110 | NEW.type LIKE '(EUR) Transfer Out to%' OR
|
---|
| 111 | NEW.type LIKE '(GBP) Transfer Out to%' THEN
|
---|
| 112 |
|
---|
| 113 | -- Extract recipient username and insert into transfer table
|
---|
| 114 | INSERT INTO transfer(s_id, r_id)
|
---|
| 115 | SELECT NEW.account_id,
|
---|
| 116 | (SELECT id FROM account
|
---|
| 117 | WHERE username = TRIM(SUBSTRING(NEW.type FROM POSITION('Transfer Out to ' IN NEW.type) + 15))
|
---|
| 118 | LIMIT 1);
|
---|
| 119 |
|
---|
| 120 | END IF;
|
---|
| 121 |
|
---|
| 122 | RETURN NEW;
|
---|
| 123 | END;
|
---|
| 124 | $$ LANGUAGE plpgsql;
|
---|
| 125 |
|
---|
| 126 | CREATE TRIGGER after_transaction2
|
---|
| 127 | AFTER INSERT ON transaction
|
---|
| 128 | FOR EACH ROW
|
---|
| 129 | EXECUTE FUNCTION after_transaction_trigger2();
|
---|
| 130 |
|
---|
| 131 | SELECT
|
---|
| 132 | tm.s_account_id AS sender_id,
|
---|
| 133 | a_s.username AS sender_username,
|
---|
| 134 | tm.r_account_id AS receiver_id,
|
---|
| 135 | a_r.username AS receiver_username,
|
---|
| 136 | tm.t_id,
|
---|
| 137 | t.timestamp,
|
---|
| 138 | t.amount
|
---|
| 139 |
|
---|
| 140 | FROM
|
---|
| 141 | transferred_money tm
|
---|
| 142 | JOIN
|
---|
| 143 | account a_s ON tm.s_account_id = a_s.id
|
---|
| 144 | JOIN
|
---|
| 145 | account a_r ON tm.r_account_id = a_r.id
|
---|
| 146 | JOIN
|
---|
| 147 | "transaction" t ON tm.t_id = t.id;
|
---|
| 148 |
|
---|
| 149 | SELECT
|
---|
| 150 | tm.s_account_id AS sender_id,
|
---|
| 151 | a_s.username AS sender_username,
|
---|
| 152 | tm.r_account_id AS receiver_id,
|
---|
| 153 | a_r.username AS receiver_username,
|
---|
| 154 | tm.t_id,
|
---|
| 155 | t.timestamp,
|
---|
| 156 | t.amount
|
---|
| 157 |
|
---|
| 158 | FROM
|
---|
| 159 | transferred_money tm
|
---|
| 160 | JOIN
|
---|
| 161 | account a_s ON tm.s_account_id = a_s.id
|
---|
| 162 | JOIN
|
---|
| 163 | account a_r ON tm.r_account_id = a_r.id
|
---|
| 164 | JOIN
|
---|
| 165 | "transaction" t ON tm.t_id = t.id
|
---|
| 166 | WHERE
|
---|
| 167 | timestamp<'"2025-04-01 22:22:00.000000"';
|
---|
| 168 |
|
---|
| 169 | SELECT
|
---|
| 170 | tm.s_account_id AS sender_id,
|
---|
| 171 | a_s.username AS sender_username,
|
---|
| 172 | tm.r_account_id AS receiver_id,
|
---|
| 173 | a_r.username AS receiver_username,
|
---|
| 174 | tm.t_id,
|
---|
| 175 | t.timestamp,
|
---|
| 176 | t.amount,
|
---|
| 177 | tm.currency
|
---|
| 178 |
|
---|
| 179 | FROM
|
---|
| 180 | transferred_money tm
|
---|
| 181 | JOIN
|
---|
| 182 | account a_s ON tm.s_account_id = a_s.id
|
---|
| 183 | JOIN
|
---|
| 184 | account a_r ON tm.r_account_id = a_r.id
|
---|
| 185 | JOIN
|
---|
| 186 | "transaction" t ON tm.t_id = t.id
|
---|
| 187 | WHERE tm.currency='(EUR)'
|
---|
| 188 | ORDER BY timestamp;
|
---|
| 189 |
|
---|
| 190 | SELECT
|
---|
| 191 | max(t.amount) as maximum,
|
---|
| 192 | avg(t.amount) as "average",
|
---|
| 193 | min(t.amount) as minimum
|
---|
| 194 |
|
---|
| 195 | FROM
|
---|
| 196 | transferred_money tm
|
---|
| 197 | JOIN
|
---|
| 198 | account a_s ON tm.s_account_id = a_s.id
|
---|
| 199 | JOIN
|
---|
| 200 | account a_r ON tm.r_account_id = a_r.id
|
---|
| 201 | JOIN
|
---|
| 202 | "transaction" t ON tm.t_id = t.id
|
---|
| 203 | WHERE tm.currency='(USD)';
|
---|
| 204 |
|
---|
| 205 |
|
---|
| 206 | WITH recent_activity AS (
|
---|
| 207 | SELECT account_id, COUNT(*) AS activity_count
|
---|
| 208 | FROM "transaction"
|
---|
| 209 | WHERE timestamp >= NOW() - INTERVAL '30 days'
|
---|
| 210 | GROUP BY account_id
|
---|
| 211 | )
|
---|
| 212 |
|
---|
| 213 | SELECT a.id AS account_id,
|
---|
| 214 | a.username,
|
---|
| 215 | a.email,
|
---|
| 216 | COALESCE(ra.activity_count, 0) AS recent_transactions
|
---|
| 217 | FROM account a
|
---|
| 218 | LEFT JOIN recent_activity ra ON a.id = ra.account_id
|
---|
| 219 | ORDER BY recent_transactions DESC
|
---|
| 220 | LIMIT 1;
|
---|
| 221 |
|
---|
| 222 |
|
---|
| 223 | WITH deposit_totals AS (
|
---|
| 224 | SELECT account_id, SUM(amount) AS total_deposit
|
---|
| 225 | FROM deposit
|
---|
| 226 | GROUP BY account_id
|
---|
| 227 | )
|
---|
| 228 |
|
---|
| 229 | SELECT a.id AS account_id,
|
---|
| 230 | a.username,
|
---|
| 231 | a.email,
|
---|
| 232 | COALESCE(dt.total_deposit, 0) AS total_deposit,
|
---|
| 233 | RANK() OVER (ORDER BY COALESCE(dt.total_deposit, 0) DESC) AS deposit_rank
|
---|
| 234 | FROM account a
|
---|
| 235 | LEFT JOIN deposit_totals dt ON a.id = dt.account_id
|
---|
| 236 | ORDER BY deposit_rank
|
---|
| 237 | LIMIT 3;
|
---|
| 238 |
|
---|
| 239 | CREATE INDEX idx_deposit_account_id_amount ON deposit (account_id, amount);
|
---|
| 240 |
|
---|
| 241 |
|
---|
| 242 | WITH transfer_amount AS (
|
---|
| 243 | SELECT t.s_id AS account_id, SUM(tr.amount) AS total_transfer
|
---|
| 244 | FROM transfer t
|
---|
| 245 | JOIN "transaction" tr ON t.id = tr.id
|
---|
| 246 | GROUP BY t.s_id
|
---|
| 247 |
|
---|
| 248 | UNION ALL
|
---|
| 249 |
|
---|
| 250 | SELECT t.r_id AS account_id, SUM(tr.amount) AS total_transfer
|
---|
| 251 | FROM transfer t
|
---|
| 252 | JOIN "transaction" tr ON t.id = tr.id
|
---|
| 253 | GROUP BY t.r_id
|
---|
| 254 | ),
|
---|
| 255 |
|
---|
| 256 | aggregated_transfers AS (
|
---|
| 257 | SELECT account_id, SUM(total_transfer) AS total_transfer_amount
|
---|
| 258 | FROM transfer_amount
|
---|
| 259 | GROUP BY account_id
|
---|
| 260 | )
|
---|
| 261 |
|
---|
| 262 | SELECT a.id AS account_id,
|
---|
| 263 | a.username,
|
---|
| 264 | a.email,
|
---|
| 265 | COALESCE(at.total_transfer_amount, 0) AS total_transfer_amount,
|
---|
| 266 | RANK() OVER (ORDER BY COALESCE(at.total_transfer_amount, 0) DESC) AS transfer_rank
|
---|
| 267 | FROM account a
|
---|
| 268 | LEFT JOIN aggregated_transfers at ON a.id = at.account_id
|
---|
| 269 | ORDER BY transfer_rank
|
---|
| 270 | LIMIT 2;
|
---|
| 271 |
|
---|
| 272 |
|
---|
| 273 | WITH transfer_frequency AS (
|
---|
| 274 | SELECT t.s_id AS account_id, COUNT(*) AS transfer_count
|
---|
| 275 | FROM transfer t
|
---|
| 276 | GROUP BY t.s_id
|
---|
| 277 |
|
---|
| 278 | UNION ALL
|
---|
| 279 |
|
---|
| 280 | SELECT t.r_id AS account_id, COUNT(*) AS transfer_count
|
---|
| 281 | FROM transfer t
|
---|
| 282 | GROUP BY t.r_id
|
---|
| 283 | )
|
---|
| 284 |
|
---|
| 285 | SELECT *
|
---|
| 286 | FROM (
|
---|
| 287 | SELECT a.id AS account_id,
|
---|
| 288 | a.username,
|
---|
| 289 | a.email,
|
---|
| 290 | tf.transfer_count,
|
---|
| 291 | RANK() OVER (ORDER BY tf.transfer_count DESC) AS transfer_rank
|
---|
| 292 | FROM account a
|
---|
| 293 | JOIN transfer_frequency tf ON a.id = tf.account_id
|
---|
| 294 | ) ranked_accounts
|
---|
| 295 | WHERE transfer_rank <= 2
|
---|
| 296 | ORDER BY transfer_rank;
|
---|
| 297 |
|
---|
| 298 |
|
---|
| 299 |
|
---|
| 300 |
|
---|
| 301 | CREATE INDEX idx_transfer_s_id ON transfer(s_id);
|
---|
| 302 |
|
---|
| 303 |
|
---|
| 304 | CREATE INDEX idx_transfer_r_id ON transfer(r_id);
|
---|
| 305 |
|
---|
| 306 | CREATE INDEX idx_account_id ON account(id);
|
---|
| 307 |
|
---|
| 308 |
|
---|
| 309 |
|
---|
| 310 |
|
---|
| 311 | -- create index client on account(username, email, balance);
|
---|
| 312 |
|
---|
| 313 |
|
---|
| 314 | -- SELECT indexname, tablename
|
---|
| 315 | -- FROM pg_indexes
|
---|
| 316 | -- WHERE tablename = 'account';
|
---|
| 317 |
|
---|
| 318 | -- select * from account;
|
---|
| 319 | -- select * from "transaction";
|
---|
| 320 |
|
---|
| 321 | create index form on "transaction"(currency,"type",timestamp);
|
---|
| 322 |
|
---|
| 323 | SET enable_seqscan = off;
|
---|
| 324 |
|
---|
| 325 |
|
---|
| 326 |
|
---|