How can I update every fields data when remove rows - sql

I'm looking for an way to update some rows right after I deleted some rows on MariaDB.
For examples, my talbes are look like:
--------------------------------------
| main_id | name | value | sub_id |
--------------------------------------
| 1 | DRINKS | 1000 | COKE |
| 1 | DRINKS | 2000 | BEER |
| 1 | DRINKS | 0600 | WATER |
| 2 | SALAD | 2000 | Peanut |
| 3 | BREADS | 1500 | FLAT |
| 3 | BREADS | 1000 | TOAST |
| 4 | BEEF | 3000 | SAUSAGE|
...
When I remove '2' SALAD, I want to update every rows main_id to main_id-1 like
--------------------------------------
| main_id | name | value | sub_id |
--------------------------------------
| 1 | DRINKS | 1000 | COKE |
| 1 | DRINKS | 2000 | BEER |
| 1 | DRINKS | 0600 | WATER |
| 2 | BREADS | 1500 | FLAT |
| 2 | BREADS | 1000 | TOAST |
| 3 | BEEF | 3000 | SAUSAGE|
...
// | 2 | SALAD | 2000 | Peanut | has removed so every main_id updated.
I cannot use PRIMARY KEY, because the things are so many duplicated.
If I have to join every rows, then I'm worried about performance, so I cannot find the way to solve the problem.
Thanks for your help.

After the Delete statement :
DELETE FROM t WHERE main_id = 2;
an Update statement containing Analytic Functions might be issued provided your DB version is 10.2+ :
UPDATE t
JOIN (WITH t2 AS
(
SELECT LAG(main_id,1) OVER (ORDER BY main_id) AS lg, t.*
FROM t
)
SELECT t2.*,
1 + SUM(CASE WHEN COALESCE(lg,main_id) = main_id THEN 0 ELSE 1 END )
OVER (ORDER BY main_id) AS new_id
FROM t2 ) t2
ON t.main_id = t2.main_id
SET t.main_id = t2.new_id;
to get main_id - 1 is updated for main_id column for main_id >2 for this individual case.
A Delete Trigger containing an Update cannot be applied on the same because of mutating trigger problem.
Demo

Related

how to insert into sql table additional values from second table if primary ids both start with 1?

the supply table:
supply_id | title | author | price | amount |
+-----------+----------------+------------------+--------+--------+
| 1 | Лирика | Пастернак Б.Л. | 518.99 | 2 |
| 2 | Черный человек | Есенин С.А. | 570.20 | 6 |
| 3 | Белая гвардия | Булгаков М.А. | 540.50 | 7 |
| 4 | Идиот | Достоевский Ф.М. | 360.80 | 3
I am trying to insert into book , all the values from supply:
+---------+-----------------------+------------------+--------+--------+
| book_id | title | author | price | amount |
+---------+-----------------------+------------------+--------+--------+
| 1 | Мастер и Маргарита | Булгаков М.А. | 670.99 | 3 |
| 2 | Белая гвардия | Булгаков М.А. | 540.50 | 5 |
| 3 | Идиот | Достоевский Ф.М. | 460.00 | 10 |
| 4 | Братья Карамазовы | Достоевский Ф.М. | 799.01 | 2 |
| 5 | Стихотворения и поэмы | Есенин С.А. | 650.00 | 15 |
+---------+-----------------------+------------------+--------+--------+
insert into book(title,author,price,amount)
select * from supply;
the primary ids conflict with each other - both tables start with id '1'
ERROR 1136: Column count doesn't match value count at row 1
Your columns in insert and select mismatches. You need to give explicit names of the columns instead of * in SELECT clause.
Try this:
insert into book(title,author,price,amount)
select title,author,price,amount from supply;

How to write a sql script that cursors through a table and inserts into a different table

I am new to sql server i have the following table structure that contains more than a thousand rows.
But for example purposes this is what it would look like
Table Import
+------+---------+------------+------------+------------+------------+------------+
| Name | Code | SocksTotal | GlovesTotal| JeansTotal | ShirtsTotal| shoesTotal |
+------+---------+------------+------------+------------+------------+------------+
| OT | 45612 | 2 | 1 | 0 | 1 | 4 |
| OT | 1234 | 0 | 1 | 0 | 0 | 0 |
| US | 45896| 0 | 0 | 0 | 0 | 0 |
+------+---------+------------+------------+------------+------------+------------+
and a second table called Items follows
+------+---------+
| ID | Item |
+------+---------+
| 1 | socks |
| 2 | Gloves|
| 3 | Jeans |
| 4 | Shirts|
| 5 | shoes |
+------+---------+
from the above tables i need to write a script that would be inserted into a different table called ImportItems_Summary.
the expected output is
+------+---------+------------+------------+
| Id | Code | Items_id |Import_total|
+------+---------+------------+------------+
| 1 | 45612 | 1 | 2 |
| 2 | 45612 | 2 | 1 |
| 3 | 45612 | 4 | 1 |
| 4 | 45612 | 5 | 4 |
| 5 | 1234 | 2 | 1 |
+------+---------+------------+------------+
as you can see here that code 45612 now has 4 entries into the ImportItems_summary table where the items is not equal to 0 and the Items_id is linked to the Items table ID column.
How can i achieve the above output?.. I read up and saw a cursor might help but i am not sure how to implement this
One method uses cross apply to unpivot the columns of the unnormalized table to rows, then brings the items table with a join, and finally inserts in the target table:
insert into ImportItems_Summary (code, items_id, import_total)
select im.code, it.items_id, x.import_total
from import im
cross apply (values
('socks', sockstotal),
('gloves', glovestotal),
('jeans', jeanstotal),
('shirts', shirtstotal),
('shoes', shoestotal)
) x(item, import_total)
inner join items it on it.item = x.item

Outer Join multible tables keeping all rows in common colums

I'm quite new to SQL - hope you can help:
I have several tables that all have 3 columns in common: ObjNo, Date(year-month), Product.
Each table has 1 other column, that represents an economic value (sales, count, netsales, plan ..)
I need to join all tables on the 3 common columns giving. The outcome must have one row for each existing combination of the 3 common columns. Not every combination exists in every table.
If I do full outer joins, I get ObjNo, Date, etc. for each table, but only need them once.
How can I achieve this?
+--------------+-------+--------+---------+-----------+
| tblCount | | | | |
+--------------+-------+--------+---------+-----------+
| | ObjNo | Date | Product | count |
| | 1 | 201601 | Snacks | 22 |
| | 2 | 201602 | Coffee | 23 |
| | 4 | 201605 | Tea | 30 |
| | | | | |
| tblSalesPlan | | | | |
| | ObjNo | Date | Product | salesplan |
| | 1 | 201601 | Beer | 2000 |
| | 2 | 201602 | Sancks | 2000 |
| | 5 | 201605 | Tea | 2000 |
| | | | | |
| | | | | |
| tblSales | | | | |
| | ObjNo | Date | Product | Sales |
| | 1 | 201601 | Beer | 1000 |
| | 2 | 201602 | Coffee | 2000 |
| | 3 | 201603 | Tea | 3000 |
+--------------+-------+--------+---------+-----------+
Thx
Devon
It sounds like you're using SELECT * FROM... which is giving you every field from every table. You probably only want to get the values from one table, so you should be explicit about which fields you want to include in the results.
If you're not sure which table is going to have a record for each case (i.e. there is not guaranteed to be a record in any particular table) you can use the COALESCE function to get the first non-null value in each case.
SELECT COALESCE(tbl1.ObjNo, tbl2.ObjNo, tbl3.ObjNo) AS ObjNo, ....
tbl1.Sales, tbl2.Count, tbl3.Netsales

SQL compare multiple rows or partitions to find matches

The database I'm working on is DB2 and I have a problem similar to the following scenario:
Table Structure
-------------------------------
| Teacher Seating Arrangement |
-------------------------------
| PK | seat_argmt_id |
| | teacher_id |
-------------------------------
-----------------------------
| Seating Arrangement |
-----------------------------
|PK FK | seat_argmt_id |
|PK | Row_num |
|PK | seat_num |
|PK | child_name |
-----------------------------
Table Data
------------------------------
| Teacher Seating Arrangement|
------------------------------
| seat_argmt_id | teacher_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
------------------------------
---------------------------------------------------
| Seating Arrangement |
---------------------------------------------------
| seat_argmt_id | row_num | seat_num | child_name |
| 1 | 1 | 1 | Abe |
| 1 | 1 | 2 | Bob |
| 1 | 1 | 3 | Cat |
| | | | |
| 2 | 1 | 1 | Abe |
| 2 | 1 | 2 | Bob |
| 2 | 1 | 3 | Cat |
| | | | |
| 3 | 1 | 1 | Abe |
| 3 | 1 | 2 | Cat |
| 3 | 1 | 3 | Bob |
| | | | |
| 4 | 1 | 1 | Abe |
| 4 | 1 | 2 | Bob |
| 4 | 1 | 3 | Cat |
| 4 | 2 | 2 | Dan |
---------------------------------------------------
I want to see where there are duplicate seating arrangements for a teacher. And by duplicates I mean where the row_num, seat_num, and child_name are the same among different seat_argmt_id for one teacher_id. So with the data provided above, only seat id 1 and 2 are what I would want to pull back, as they are duplicates on everything but the seat id. If all the children on the 2nd table are exact (sans the primary & foreign key, which is seat_argmt_id in this case), I want to see that.
My initial thought was to do a count(*) group by row#, seat#, and child. Everything with a count of > 1 would mean it's a dupe and = 1 would mean it's unique. That logic only works if you are comparing single rows though. I need to compare multiple rows. I cannot figure out a way to do it via SQL. The solution I have involves going outside of SQL and works (probably). I'm just wondering if there is a way to do it in DB2.
Does this do what you want?
select d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
from seatingarrangement sa join
data d
on sa.seat_argmt_id = d.seat_argmt_id
group by d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
having count(*) > 1;
EDIT:
If you want to find two arrangements that are the same:
select sa1.seat_argmt_id, sa2.seat_argmt_id
from seatingarrangement sa1 join
seatingarrangement sa2
on sa1.seat_argmt_id < sa2.seat_argmt_id and
sa1.row_num = sa2.row_num and
sa1.seat_num = sa2.seat_num and
sa1.child_name = sa2.child_name
group by sa1.seat_argmt_id, sa2.seat_argmt_id
having count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa1.seat_argmt_id) and
count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa2.seat_argmt_id);
This finds the matches between two arrangements and then verifies that the counts are correct.

How to extract from two tables and join them like the example

Table A ............................. Table B
+-----------+ .........................+-----------+
|Id | Sum1| .........................|Id |Sum2 |
| 1 | 1500 | .........................| 1 | 2300|
| 1 | 2500 | .........................| 1 | 1500|
| 1 | 1300 | .........................+-----------+
+-----------+
I have Table A and Table B. I need query to result like this:
Result
+-----------------------+
|Id | Sum1| |Sum2 |
| 1 | 1500 | |......0|
| 1 | 2500 | |......0|
| 1 | 1300 | |......0|
| 1 | 0....| | 2300 |
| 1 | 0....| | 1500 |
+-----------------------+
I need to filter with id and the result should be like the third table where I can divide left and right column from Table A and Table B.
Please help. I tried with other examples but I didn't succeed.
If you want that output, you can use:
SELECT ID, Sum1, 0 AS Sum2
FROM TableA
UNION ALL
SELECT ID, 0 AS Sum1, Sum2
FROM TableB
Not sure why it would be a useful resultset, though ...