List customer ID, name and all of his/her accounts - oracle

customers:
+------------+--------------+
| cid | Name |
+------------+--------------+
| 1 | Bob |
| 2 | John |
| 3 | Jane |
+------------+--------------+
accounts:
+------------+--------------+
| aid | type |
+------------+--------------+
| 1 | Checking |
| 2 | Saving |
| 3 | CD |
+------------+--------------+
transactions:
+------------+--------------+--------------+
| tid | cid | aid |
+------------+--------------+--------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 1 |
+------------+--------------+--------------+
I am trying to write a plsql procedure that, given the customer id as a parameter, will display his/her id, name and all accounts. Displaying the id and name is simple enough. What I'm not sure about is how to get all the accounts that are linked to the customer id and how to retrieve more than a single account.

An ideea can be:
select c.cid, c.name, a.type
from customers c
left join transactions t on (t.cid = c.cid)
left join accounts a on (a.aid = t.aid)
where c.cid = :customer_id
group by c.cid, c.name, a.type;
the group by is needed because can be more transactions.
Further, if you want to see one line:
select cid, name, LISTAGG(type, ',') WITHIN GROUP (ORDER BY type) as account_types
from(
select distinct c.cid, c.name, a.type
from customers c
left join transactions t on (t.cid = c.cid)
left join accounts a on (a.aid = t.aid)
where c.cid = :customer_id
)
group by cid, name;
Putting this into a stored procedure/function is too simple, so I let it to you.

Related

Delete query inoracle db is fast but select query running too long

I have below table with 160,000 rows. When I use SELECT ID FROM mytable WHERE id NOT IN ( SELECT max(id) FROM mytable GROUP BY user_id); query is running very long and not finishing (I wait for 1 Hr) but when I use delete FROM mytable WHERE id NOT IN (SELECT max(id) FROM mytable GROUP BY user_id); query is running in 0.5 seconds. Why??
---------------------------------------------------------------------------------------------------
| id | MyTimestamp | Name | user_id ...
----------------------------------------------------------------------------------------------------
| 0 | 1657640396 | John | 123581 ...
| 1 | 1657638832 | Tom | 168525 ...
| 2 | 1657640265 | Tom | 168525 ...
| 3 | 1657640292 | John | 123581 ...
| 4 | 1657640005 | Jack | 896545 ...
-----------------------------------------------------------------------------------------

how to select only external tranzactions(column values) in oracle?

i have a first table with id_client,id_card (info table)
and second with id_debet,id_credit,value,vale_info (tranzaction table)
first table second table
______________________ ________________________________________________________
|id_client | id_card | |id_debet |id_credit | value | value info |
|50102411 | 5166 | | 5166 | 5167 | 300$ | transfer to client card |
|50102411 | 5167 | | 5167 | 4931239 | 100$ | UBER taxi NY |
|50102412 | 5168 | | 5168 | 5169 | 200$ | transfer to client card |
|50102412 | 5169 | | 5169 | 3582934 | 120$ | rent hotel room |
______________________ ________________________________________________________
id_debet -> spend from your card
id_Debet -> replenishment to your card
and i want to select only external tranzaction not between card clients
for ex
if 5166 send money to 5167 i skip this tranzaction
if 5166 send to another card i select it etc
You can use a NOT EXISTS query to find all transactions in the second table that have an id_debet or id_credit which is not in the first table:
SELECT *
FROM table2 t2
WHERE NOT EXISTS (SELECT *
FROM table1 t1
WHERE t1.id_card = t2.id_debet)
OR NOT EXISTS (SELECT *
FROM table1 t1
WHERE t1.id_card = t2.id_credit)
Output:
id_debet id_credit value value info
5167 4931239 100$ UBER taxi NY
5169 3582934 120$ rent hotel room
Demo on dbfiddle
You can use GROUP BY and HAVING as follows:
SELECT T.id_debet, T.id_credit, T.value, T.value info FROM tranzaction T
JOIN info I ON I.id_card IN (T.id_debet, T.id_credit)
GROUP BY T.id_debet, T.id_credit, T.value, T.value
HAVING COUNT(1) = 1

Query optimization to split all authorized pairs values in two columns with defaults

I would like to optimize oracle query to transform table with all authorized pair values in two columns. The first with exceptions of authorized by default and the second exceptions of forbidden by default.
For example :
| ROOM | USER AUTHORIZED |
| ROOM1 | A |
| ROOM2 | A |
| ROOM2 | B |
| ROOM3 | B |
| ROOM4 | B |
| ROOM5 | B |
| ROOM2 | C |
| ROOM3 | C |
| ROOM4 | C |
To:
ROOM | USER EXCEPTION AUTHORIZED | USER EXCEPTION FORBIDDEN |
ROOM1| A | B;C
ROOM2| A |
ROOM3| |
ROOM4| |
ROOM5| | C
I used this query to get exception forbidden:
WITH USERS
AS( SELECT USER FROM ROOM_USERS GROUP BY USER HAVING count(*)>(SELECT count(*)/2 FROM ROOM_USERS )),
ROOMS
AS( SELECT DISTINCT(ROOM) as room FROM ROOM_USERS)
SELECT ROOM, LISTAGG(USER, ';') WITHIN GROUP (ORDER BY USER)
FROM USERS, ROOMS
WHERE USERS.user||ROOMS.room NOT IN (
SELECT user||room
FROM ROOMS_USERS
)
GROUP BY room;

Convert raw query into laravel eloquent

I have this written and working as a raw SQL query, but I am trying to convert it to a more Laravel eloquent / query builder design instead of just a raw query.
My table structure like this:
Table One (Name model)
______________
| id | name |
|------------|
| 1 | bob |
| 2 | jane |
--------------
Table Two (Date Model)
_________________________________
| id | table_1_id | date |
|-------------------------------|
| 1 | 1 | 2000-01-01 |
| 2 | 1 | 2000-01-31 |
| 4 | 1 | 2000-02-28 |
| 5 | 1 | 2000-03-03 |
| 6 | 2 | 2000-01-03 |
| 7 | 2 | 2000-01-05 |
---------------------------------
I am returning only the the highest (most recent) dates from table 2 (Dates model) that match the user bob from table 1 (Name model).
For instance, in the example above, I return this from my query
2000-01-31
2000-02-28
2000-03-03
Here is what I am doing now (which works), but i'm just not sure how to use YEAR, MONTH and MAX with laravel.
DB::select(
DB::raw("
SELECT MAX(date) as max_date
FROM table_2
INNER JOIN table_1 ON table_1.id = table_2.table_1_id
WHERE table_1.name = 'bob'
GROUP BY YEAR(date), MONTH(date)
ORDER BY max_date DESC
")
);
Try this code if any problem then,
DB::table('table_1')->join('table_2', 'table_1.id','=','table_2.table_1_id')
->select(DB::raw('MAX(date) as max_date'),DB::raw('YEAR(date) year, MONTH(date) month'),'table_1.name')
->where('name','bob')
->groupBy('year','month')
->orderBy('max_date')
->get();
If any problem with above code then feel free to ask.

HIVE Pivot and Sum

I have a table that I am trying to figure out how to pivot and sum based on the values in a second column.
Example input:
|own|pet|qty|
|---|---|---|
|bob|dog| 2 |
|bob|dog| 3 |
|bob|dog| 1 |
|bob|cat| 1 |
|jon|dog| 1 |
|jon|cat| 1 |
|jon|cat| 1 |
|jon|cow| 4 |
|sam|dog| 3 |
|sam|cow| 1 |
|sam|cow| 2 |
Example output:
|own|dog|cat|cow|
|---|---|---|---|
|bob| 6 | 1 | |
|jon| 1 | 2 | 4 |
|sam| 1 | | 3 |
Use case and sum():
select own, sum(case when pet='dog' then qty end) as dog,
sum(case when pet='cat' then qty end) as cat,
sum(case when pet='cow' then qty end) as cow
from your_table
group by own;
For dynamic data you can use MAP
select own
,str_to_map(concat_ws(',',collect_list(concat(pet,':',cast(qty as string))))) as pet_qty
from (select own,pet
,sum(qty) qty
from mytable
group by own,pet
) t
group by own
;
+-----+---------------------------------+
| own | pet_qty |
+-----+---------------------------------+
| bob | {"cat":"1","dog":"6"} |
| jon | {"cat":"2","cow":"4","dog":"1"} |
| sam | {"cow":"3","dog":"3"} |
+-----+---------------------------------+

Resources