Automatically Update 2 Table or Multiple in Mysql - mysql

I have problem
I want to ask, how to change the data that has been entered into the table rekap_nilai. which is where the table is rekapan rekap_nilai total of table nilai_student.
I enter a table B based on trigger
mysql> select * from nilai_student;
+----+-------+------+-------+
| id | name | idmp | nilai |
+----+-------+------+-------+
| 1 | Udin | 1 | 80 |
| 2 | Udin | 2 | 60 |
| 3 | Mamat | 1 | 75 |
+----+-------+------+-------+
table rekap_nilai
mysql> desc rekap_nilai;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idstudent | int(11) | YES | | NULL | |
| name | varchar(100) | YES | | NULL | |
| nilai | double | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> select * from rekap_nilai;
+----+-----------+-------+-------+
| id | idstudent | name | nilai |
+----+-----------+-------+-------+
| 1 | 1 | Udin | 140 |
| 2 | 2 | Mamat | 75 |
+----+-----------+-------+-------+
2 rows in set (0.00 sec)
What if there was a remedial student conduct and when update table nilai_student in column nilai, ​​automatically in table rekap_nilai in column nilai
example
now name 'Udin' have nilai 60 in id 2, and he want remedial. when he was remedial, I want to update he's nilai = 70 , and then in table rekap_nilai. udin automatically update to nilai = 150

You can write a trigger which gets executed on update of table nilai_student , some thing like below
Delimiter ///
create trigger update_rekap_nilai after update on nilai_student
for each row begin
update recap_nilai set nilai = nilai - Old.nilai + New.nilai where name=Old.name
end;
///
Delimiter ;
Hope this helps !!

Related

Mysql: How to create a column which is the difference between a column in a Table & another column in a View

In the database 'college2' there are 3 TABLES:'student, course & enrolment', and one(1) VIEW:'enrolment_status', which is created using the following command:
CREATE VIEW enrolment_status AS
SELECT code, COUNT(id)
FROM enrolment
GROUP BY code;
Explain command for 'course,enrolment and enrolment_status' results in:
mysql> EXPLAIN course;
+---------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| code | char(8) | NO | PRI | NULL | |
| name | varchar(90) | YES | MUL | NULL | |
| max_enrolment | char(2) | YES | | NULL | |
+---------------+-------------+------+-----+---------+-------+
3 rows in set (0.09 sec)
mysql> explain enrolment;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | char(6) | YES | MUL | NULL | |
| code | char(8) | YES | MUL | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.02 sec)
mysql> explain enrolment_status;
+-----------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+-------+
| code | char(8) | YES | | NULL | |
| COUNT(id) | bigint(21) | NO | | 0 | |
+-----------+------------+------+-----+---------+-------+
2 rows in set (0.18 sec)
'max_enrolment' column in 'course' TABLE is the maximum allowed # of student for each course, say 10 or 20.
'count(id)' column in 'enrolment_status' VIEW (not table) is actual # of students enrolled in each course.
'id' column in 'enrolment' TABLE is the student id enrolled in a course.
HERE'S MY QUESTION:
I want to have the '# of seats left' which is the difference between 'max_enrolment' column and 'count(id)' column.
'#of seats left' can be a stand alone table or view or a column added to any of the above tables. How can i do this:
I tried many commands including the following,
CREATE VIEW seats_left AS (
SELECT course.code, course.max_enrolment - enrolment_status.count
FROM course, enrolment_status
WHERE course.code = enrolment_status.code);
...which gives me the following error message:
ERROR 1054 (42S22): Unknown column 'enrolment_status.count' in 'field list'
mysql> SELECT*FROM enrolment_status;
+----------+-----------+
| code | COUNT(id) |
+----------+-----------+
| COMP9583 | 7 |
| COMP9585 | 9 |
| COMP9586 | 7 |
| COMP9653 | 7 |
| COMP9654 | 7 |
| COMP9655 | 8 |
| COMP9658 | 7 |
+----------+-----------+
7 rows in set (0.00 sec)
mysql> SELECT code, max_enrolment FROM course;
+----------+---------------+
| code | max_enrolment |
+----------+---------------+
| COMP9583 | 10 |
| COMP9585 | 15 |
| COMP9586 | 15 |
| COMP9653 | 12 |
| COMP9654 | 10 |
| COMP9655 | 12 |
| COMP9658 | 12 |
+----------+---------------+
7 rows in set (0.00 sec)
+----------+---------------------+
| code | max_enrolment - cnt |
+----------+---------------------+
| COMP9583 | 9 |
| COMP9585 | 14 |
| COMP9586 | 14 |
| COMP9653 | 11 |
| COMP9654 | 9 |
| COMP9655 | 11 |
| COMP9658 | 11 |
+----------+---------------------+
7 rows in set (0.09 sec)
Try to use an acronym for in the view.
CREATE VIEW enrolment_status AS
SELECT code, COUNT(id) count
FROM enrolment
GROUP BY code;
Then you should be able to do this:
CREATE VIEW seats_left AS (
SELECT course.code, course.max_enrolment - enrolment_status.count
FROM course, enrolment_status
WHERE course.code = enrolment_status.code);
If you cannot change the view, then you must use the exact same name in the query:
CREATE VIEW seats_left AS (
SELECT course.code, course.max_enrolment - enrolment_status.'count(id)'
FROM course, enrolment_status
WHERE course.code = enrolment_status.code);
Try this:
SELECT b.`code`,max_enrolment - cnt from
(select `code`, cnt from
(select count(1) as cnt,`code` from enrolment_status
GROUP BY `code`) as a) as a
LEFT JOIN
(SELECT code,max_enrolment from course) as b
on a.`code` = b.`code`
You can change left join to right join

Column value of first table needs to be update automatically whenever the second table row is updated or added

Column value of first table needs to be update automatically whenever the second table row is updated or added.
I have two table CcnCSR and CsrTimeReporting
mysql> select * from CcnCSR;
select * from CsrTimeReporting;
+-----------+-----------------------------------------+----------+-------------+-----------+-------------+------------+------------+------------+-------------------+--------+
| CSRNumber | Slogan | Severity | Customer | Status | CreatedDate | CcnQDate | TTS | IAdate | TotalTimeReported | Remark |
+-----------+-----------------------------------------+----------+-------------+-----------+-------------+------------+------------+------------+-------------------+--------+
| 2718122 | DIAMETER LINK FLICKS BETWEEN GGSN-CCN38 | High | IdeaIndia | NULL | 2105-03-04 | 2105-03-03 | 2015-03-28 | 2105-03-13 | NULL | NA |
| 2718133 | Auto ZR | High | AirtelIndia | Analysing | 2105-03-20 | 2105-03-23 | 2105-04-10 | NULL | NULL | NULL |
+-----------+-----------------------------------------+----------+-------------+-----------+-------------+------------+------------+------------+-------------------+--------+
2 rows in set (0.00 sec)
+-----------+-------+------------------+--------------+-------+
| CSRNumber | SeqId | TimeReportedDate | TimeReported | Shift |
+-----------+-------+------------------+--------------+-------+
| 2718122 | 1 | 2015-03-15 | 8 | NULL |
| 2718122 | 2 | 2105-03-03 | 0.5 | NULL |
| 2718122 | 3 | 2105-03-03 | 3 | NULL |
| 2718122 | 4 | 2105-03-03 | 4.5 | NULL |
| 2718122 | 5 | 2105-03-03 | 5.25 | NULL |
| 2718122 | 6 | 2105-03-05 | 7.25 | NULL |
| 2718133 | 8 | 2015-03-30 | 2 | NULL |
| 2718133 | 9 | 2015-03-31 | 2.5 | NULL |
| 2718133 | 10 | 2015-03-29 | 3.5 | NULL |
+-----------+-------+------------------+--------------+-------+
9 rows in set (0.00 sec)
Where in table CcnCSR there is column "TotalTimeReported", this column value needs to be update automatically whenever the second table column "TimeReported" is updated or new row is added.
How can i do this?
This is how you can do it
create trigger trigger_name
on CsrTimeReporting
for insert
as
begin
declare
#time_reported decimal,
#CSR_Number nvarchar(50) -- select data type as you need
select #CSR_Number = CSRNumber , #time_reported = TimeReportedDate from
CsrTimeReporting
Update CcnCSR set TotalTimeReported = #time_reported where
CSRNumber = #CSR_Number
You can do this using multiple triggers, one for insert, update, and delete:
delimiter //
create trigger trig:csrTimeReport_insert on CsrTimeReporting
after insert for each row
begin
update CcnCSR
set TotalTimeReported = TotalTimeReported + new.TimeReported
where CcnCSR.CSRNumber = new.CSRNumber;
end;//
create trigger trig:csrTimeReport_update on CsrTimeReporting
after update for each row
begin
update CcnCSR
set TotalTimeReported = TotalTimeReported + new.TimeReported - old.TimeReported
where CcnCSR.CSRNumber = new.CSRNumber;
end;//
create trigger trig:csrTimeReport_delete on CsrTimeReporting
after delete for each row
begin
update CcnCSR
set TotalTimeReported = TotalTimeReported + - old.TimeReported
where CcnCSR.CSRNumber = old.CSRNumber;
end;//
delimiter ;

mysql how to find the total number of child rows with respect to a parent

I have a table which having parent child relatiionship like this,
Employee_ID | Employee_Manager_ID | Employee_Name
--------------------------------------------------------
1 | 1 | AAAA
2 | 1 | BBBB
3 | 2 | CCCC
4 | 3 | DDDD
5 | 3 | EEEEE
Is it possible to get the count of all the employees come under a particular employee(Not only direct child,count of all the childs of child ) using a single query ?
Eg if the input = 1
output should be 4
if input = 2 ,output should be 3
thanks in advance
Suppose your table is:
mysql> SELECT * FROM Employee;
+-----+------+-------------+------+
| SSN | Name | Designation | MSSN |
+-----+------+-------------+------+
| 1 | A | OWNER | 1 |
| 10 | G | WORKER | 5 |
| 11 | D | WORKER | 5 |
| 12 | E | WORKER | 5 |
| 2 | B | BOSS | 1 |
| 3 | F | BOSS | 1 |
| 4 | C | BOSS | 2 |
| 5 | H | BOSS | 2 |
| 6 | L | WORKER | 2 |
| 7 | I | BOSS | 2 |
| 8 | K | WORKER | 3 |
| 9 | J | WORKER | 7 |
+-----+------+-------------+------+
12 rows in set (0.00 sec)
Query is:
SELECT SUPERVISOR.name AS SuperVisor,
GROUP_CONCAT(SUPERVISEE.name ORDER BY SUPERVISEE.name ) AS SuperVisee,
COUNT(*)
FROM Employee AS SUPERVISOR
INNER JOIN Employee SUPERVISEE ON SUPERVISOR.SSN = SUPERVISEE.MSSN
GROUP BY SuperVisor;
The query will produce result like:
+------------+------------+----------+
| SuperVisor | SuperVisee | COUNT(*) |
+------------+------------+----------+
| A | A,B,F | 3 |
| B | C,H,I,L | 4 |
| F | K | 1 |
| H | D,E,G | 3 |
| I | J | 1 |
+------------+------------+----------+
5 rows in set (0.00 sec)
[Answer]:
This for One level (immediate supervise) to find all supervises at all possible level you have to use while loop (use stored procedures).
Although it is possible to retrieve employees at each level and then take their UNION, we cannot, in general, specify a query such as "retrieve the supervisees of a employee at all levels" without utilizing a looping mechanism."
REFERENCE: in this slide read slid number 23.
The BOOK is " FUNDAMENTALS OF FourthEdition DATABASE SYSTEMS" in chapter "The Relational Algebra and Relational Calculus" there is a topic "Recursive Closure Operations".
Adding Query for Table creation, May be helpful to you:
mysql> CREATE TABLE IF NOT EXISTS `Employee` (
-> `SSN` varchar(64) NOT NULL,
-> `Name` varchar(64) DEFAULT NULL,
-> `Designation` varchar(128) NOT NULL,
-> `MSSN` varchar(64) NOT NULL,
-> PRIMARY KEY (`SSN`),
-> CONSTRAINT `FK_Manager_Employee` FOREIGN KEY (`MSSN`) REFERENCES Employee(SSN)
-> ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.17 sec)
You can check Table like:
mysql> DESCRIBE Employee;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| SSN | varchar(64) | NO | PRI | NULL | |
| Name | varchar(64) | YES | | NULL | |
| Designation | varchar(128) | NO | | NULL | |
| MSSN | varchar(64) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
You may try this:
SELECT
table_name.Employee_ID,
table_name.Employee_Name,
COUNT(*) AS children
FROM
table_name AS t_one
INNER JOIN table_name AS t_two ON
t_two.Employee_Manager_ID=t_one.Employee_ID
GROUP BY
t_one.Employee_ID

MySQL - retrospectively add ID that AUTO_INCREMENTs

I have table with lots of rows, and there is no id column. I'd like to go back and:
add an ID column as PRIMARY KEY with AUTO_INCREMENT
more importantly, retrospectively add an ID for all the existing rows, from oldest to newest (there is an 'updatetime' column).
Any suggestions?
Let's consider the following example:
CREATE TABLE your_table (some_value int, updatetime datetime);
INSERT INTO your_table VALUES (100, '2010-08-11 12:09:00');
INSERT INTO your_table VALUES (300, '2010-08-11 12:08:00');
INSERT INTO your_table VALUES (200, '2010-08-11 12:07:00');
INSERT INTO your_table VALUES (400, '2010-08-11 12:06:00');
INSERT INTO your_table VALUES (600, '2010-08-11 12:05:00');
INSERT INTO your_table VALUES (500, '2010-08-11 12:04:00');
INSERT INTO your_table VALUES (800, '2010-08-11 12:03:00');
First we can add the id column:
ALTER TABLE your_table ADD id int unsigned;
Now the table looks like this:
SELECT * FROM your_table;
+------------+---------------------+------+
| some_value | updatetime | id |
+------------+---------------------+------+
| 100 | 2010-08-11 12:09:00 | NULL |
| 300 | 2010-08-11 12:08:00 | NULL |
| 200 | 2010-08-11 12:07:00 | NULL |
| 400 | 2010-08-11 12:06:00 | NULL |
| 600 | 2010-08-11 12:05:00 | NULL |
| 500 | 2010-08-11 12:04:00 | NULL |
| 800 | 2010-08-11 12:03:00 | NULL |
+------------+---------------------+------+
7 rows in set (0.00 sec)
Then we can UPDATE the id column with the row number when the result set is ordered by the updatetime column:
SET #row_number := 0;
UPDATE your_table
SET your_table.id = (#row_number := #row_number + 1)
ORDER BY your_table.updatetime;
Now the table looks like this:
SELECT * FROM your_table ORDER BY id;
+------------+---------------------+----+
| some_value | updatetime | id |
+------------+---------------------+----+
| 800 | 2010-08-11 12:03:00 | 1 |
| 500 | 2010-08-11 12:04:00 | 2 |
| 600 | 2010-08-11 12:05:00 | 3 |
| 400 | 2010-08-11 12:06:00 | 4 |
| 200 | 2010-08-11 12:07:00 | 5 |
| 300 | 2010-08-11 12:08:00 | 6 |
| 100 | 2010-08-11 12:09:00 | 7 |
+------------+---------------------+----+
Then we can set the id column as the primary key, and make it NOT NULL and AUTO_INCREMENT:
ALTER TABLE your_table
MODIFY id int unsigned NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (id);
This is the new description of the table:
DESCRIBE your_table;
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| some_value | int(11) | YES | | NULL | |
| updatetime | datetime | YES | | NULL | |
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
+------------+------------------+------+-----+---------+----------------+
3 rows in set (0.04 sec)
We can now try to INSERT a new row in the table to confirm that AUTO_INCREMENT is working as expected:
INSERT INTO your_table (some_value, updatetime)
VALUES (900, '2010-08-11 12:10:00');
SELECT * FROM your_table ORDER BY id;
+------------+---------------------+----+
| some_value | updatetime | id |
+------------+---------------------+----+
| 800 | 2010-08-11 12:03:00 | 1 |
| 500 | 2010-08-11 12:04:00 | 2 |
| 600 | 2010-08-11 12:05:00 | 3 |
| 400 | 2010-08-11 12:06:00 | 4 |
| 200 | 2010-08-11 12:07:00 | 5 |
| 300 | 2010-08-11 12:08:00 | 6 |
| 100 | 2010-08-11 12:09:00 | 7 |
| 900 | 2010-08-11 12:10:00 | 8 |
+------------+---------------------+----+
8 rows in set (0.00 sec)
I'm not sure if there is an easier way to tackle this, but this approach seems to do the job.

MySQL query using INNER JOIN, Not returning what i'd expect

I'm having trouble with the following query:
SELECT costingjobtimes.TimeStamp, costingdepartment.DeptDesc, costingemployee.Name, costingjobtimes.TimeElapsed FROM costingemployee INNER JOIN (costingdepartment INNER JOIN costingjobtimes ON costingdepartment.DeptID = costingjobtimes.DeptID) ON costingemployee.EmployeeID = costingjobtimes.EmployeeID;
I would expect it to return every row in the costingjobtimes database however it's only returning 4 at current.
Basically, I have 3 tables. (costingjobtimes, costingdepartment, costingemployee) They are as follows:
mysql> DESCRIBE costingemployee
-> ;
+------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| EmployeeID | varchar(8) | | PRI | | |
| Name | text | | | | |
+------------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> DESCRIBE costingdepartment
-> ;
+----------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+-------+
| DeptID | int(10) unsigned | | PRI | 0 | |
| DeptDesc | text | | | | |
+----------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> DESCRIBE costingjobtimes
-> ;
+-------------+------------------+------+-----+---------------------+-----------
-----+
| Field | Type | Null | Key | Default | Extra
|
+-------------+------------------+------+-----+---------------------+-----------
-----+
| id | int(10) unsigned | | PRI | NULL | auto_incre
ment |
| EmployeeID | text | | | |
|
| DeptID | int(10) unsigned | | | 0 |
|
| JobNumber | text | | | |
|
| TimeElapsed | decimal(10,5) | | | 0.00000 |
|
| TimeStamp | datetime | | | 0000-00-00 00:00:00 |
|
| JobRef | text | | | |
|
+-------------+------------------+------+-----+---------------------+-----------
-----+
7 rows in set (0.00 sec)
So all the query is supposed to do is return all the rows from costingjobtimes, but put in the employees name instead of EmployeeID and Department description instead of the DeptID. Any help would be great..
Thanks in advance,
I don't know if an Inner Join is really what you are looking for teishu. Maybe you should try a normal join.
For example:
select e.Name, d.DeptDesc, j.JobNumber, j.TimeElapsed, j.TimeStamp, j.JobRef
from costingjobtimes as j
join costingdepartment as d on d.DeptID = j.DeptId
join costingemployee as e on e.EmployeeID = j.EmployeeID
This should give you a resultset with the information from the costingjobtimes table combined with the name of the employee and the description of the department.
Hope that helpes.