hi i'm just new to sql and i have a hard time deleting records. i need to Delete all the records from subjcode table where the teacher is “MARSHALL”. i used this query but i doesn't work:
delete
from subjcode
where (
select sa.sno
from subjcode sa,
teacher,
course
where teacher.tname = 'MARSHALL'
and teacher.tno = course.tno
and course.cno = sa.cno
) = subjcode.sno;
and there is the table and its columns:
subjcode: sno,cno,score
course: cno,tno,cname
teacher:tno,tname
i know that all i need is just the tname,tno, and the cno but i don't know the proper query. please help me thanks
You can delete using join:
delete s
from subjcode s
join course c on s.cno = c.cno
join teacher t on t.tno = c.tno
where t.tname = 'MARSHALL';
See this for reference:
https://dev.mysql.com/doc/refman/5.7/en/delete.html
Try this:
delete s
from subjcode s
join course c on s.cno = c.cno
join teacher t on c.tno = t.tno
where t.tname = 'MARSHALL';
Related
Hello all StackOverFlow families.
I need your help about sql query in mysql. I join four tables but result is duplicate row.
I have tried by using GROUP BY but not work.
Here is my query:
SELECT `tbl_leave`.`id`, `tbl_leave`.`staff_id`, `tbl_leave`.`type_id`, `tbl_leave`.`start_date`, `tbl_leave`.`end_date`,
`tbl_leave`.`total_days`, `tbl_leave`.`reason`, `tbl_leave_type`.`type`, `tbl_employment`.`com_id` as `comid`, `tbl_staff`.`name`
FROM `tbl_leave` JOIN
`tbl_leave_type`
ON `tbl_leave_type`.`id` = `tbl_leave`.`type_id` JOIN
`tbl_employment`
ON `tbl_employment`.`staff_id` = `tbl_leave`.`staff_id` JOIN
`tbl_staff`
ON `tbl_staff`.`id` = `tbl_leave`.`staff_id`
You can look as picture: https://imgur.com/gallery/1Ewku
And this is relationship table: https://imgur.com/gallery/ziKq3
The result I want like this : https://imgur.com/gallery/6NJpR
Thank for your valuable times for this question.
Please try
SELECT distinct `tbl_leave`.`id`, `tbl_leave`.`staff_id`,
`tbl_leave`.`type_id`, `tbl_leave`.`start_date`, `tbl_leave`.`end_date`,
`tbl_leave`.`total_days`, `tbl_leave`.`reason`, `tbl_leave_type`.`type`,
`tbl_employment`.`com_id` as `comid`, `tbl_staff`.`name`
FROM `tbl_leave` JOIN
`tbl_leave_type`
ON `tbl_leave_type`.`id` = `tbl_leave`.`type_id` JOIN
`tbl_employment`
ON `tbl_employment`.`staff_id` = `tbl_leave`.`staff_id` JOIN
`tbl_staff`
ON `tbl_staff`.`id` = `tbl_leave`.`staff_id`;
Please try this solution and let me know if is there any problem occur:
SELECT [Columns] From tbl_staff as staff
JOIN tbl_employment as emp on staff.id = = emp.staff_id
JOIN tbl_leave as leave on staff.id = = leave.staff_id
JOIN tbl_leave_type as ltype on leave.type_id = = ltype.id
Now I want to get a comments list, and I have two table named TB_COMMENT, TB_USER;
the TB_COMMENT table has three fields: WORK_ID, USER_ID, ATED_USER_ID;
the TB_USER table has three fields: USER_ID, NICKNAME.
now the front end gives me a workId, and I need to return the list include:
userId, nickname, atedUserId, atedNickname.(and the atedUserId, atedNickname may not exist).
And I just write this sql sentence:
SELECT DISTINCT TB_USER.USER_ID, TB_USER.NICKNAME, TB_COMMENT.ATED_USER_ID
FROM TB_USER, TB_COMMENT
WHERE TB_COMMENT.WORK_ID = #{workId} AND TB_COMMENT.USER_ID = TB_USER.USER_ID`
and I don't know how to get the atedNickname. Hope someone can help me, thanks.
You need one more join with TB_USER on ATED_USER_ID foreign key
SELECT DISTINCT ua.USER_ID, ua.NICKNAME, ub.USER_ID, ub.NICKNAME
FROM TB_USER ua INNER JOIN TB_COMMENT c ON ua.USER_ID = c.USER_ID
LEFT JOIN TB_USER ub ON ub.USER_ID = c.ATED_USER_ID
WHERE c.WORK_ID = #{workId}
I have three tables
user_table:
user_id
user_name
leave_type:
leave_id
leave_name
leave_taken
id
leave_id
applied_by (user_id)
approved_by (user_id)
My end result should be
Result:
leave_name
applied_by (user_name)
approved_by (user_name)
This is what I have tried and got stuck at. I'm sorry for not providing what I tried the first time I posted this question.
Option 1:
SELECT leave_type.leave_name, users.user_name as applied_by,
leaves.no_of_days, leaves.leave_date, leaves.leave_upto_date,
leaves.leave_status
from leaves
join leave_type on leaves.leave_type = leave_type.id
join users on leaves.applied_by = users.id
Option 2:
SELECT leave_type.leave_name, users.user_name as applied_by,
leaves.approved_by, leaves.no_of_days, leaves.leave_date,
leaves.leave_upto_date, leaves.leave_status, leaves.approved_on
FROM leave_type, leaves, users
WHERE leave_type.id = leaves.leave_type
AND leaves.applied_by = users.id
P.S. I'm new to MySQL & I'm not sure how to implement this.
I achieved your desired result with the following query. I'm not very sure if this is the best way though.
SELECT leave_type.leave_name, users.user_name AS applied_by,
(SELECT user_name FROM users WHERE id = leaves.approved_by) AS approved_by,
leaves.no_of_days, leaves.leave_date, leaves.leave_upto_date,
leaves.leave_status
FROM leaves
JOIN leave_type on leaves.leave_type = leave_type.id
JOIN users on leaves.applied_by = users.id;
If you need to join the same table twice, you can provide it with an alias.
In this case, the user table has been joined with two different aliases. I've made the aliases in capitals, so it's easier to find them, but of course, you can write them however you want.
SELECT
leave_type.leave_name,
APPLY_USER.user_name as applied_by,
APPROVE_USER.user_name as approved_by,
leaves.no_of_days, leaves.leave_date, leaves.leave_upto_date,
leaves.leave_status
from leaves
join leave_type on leaves.leave_type = leave_type.id
join users AS APPLY_USER on leaves.applied_by = APPLY_USER.id
join users AS APPROVE_USER on leaves.applied_by = APPROVE_USER.id
I'm trying to pull from multiple tables to insert into a table to create role assignments in moodle's database based on the categories that are created but I need it to update on duplicate key but I cant use ON DUPLICATE KEY UPDATE because the fields im trying to match on role id, context id, and user id are not primary keys in the mdl_role_assignments table.
insert into vclassmoodle.mdl_role_assignments (roleid,contextid,userid,timemodified,modifierid,itemid,sortorder) select
mdl_role.id as roleid, mdl_context.id as contextid, mdl_user.id as userid, unix_timestamp() as timemodified, 3 as modifierid, 0 as itemid, 0 as sortorder
from
mdl_context
left join
mdl_course_categories ON mdl_context.instanceid = mdl_course_categories.id
left join
mdl_user ON mdl_course_categories.idnumber = mdl_user.idnumber
join
mdl_role ON mdl_role.shortname = 'manager'
where mdl_context.contextlevel = 40 and mdl_course_categories.depth > 1
Let me know if I need to clarify on anything
Thanks
Just been having a look at the function role_assign() in /lib/accesslib.php
If there is a duplicate then it doesn't update, so you could just ignore duplicates.
Although you should really use the role_assign() function rather than insert data directly. In case the role assignment changes in the future, but also because it triggers a role_assigned event which might be used elsewhere.
Still use your query but ignore existing records and create a loop to call role_assign(), something like this
SELECT mdl_role.id as roleid,
mdl_context.id as contextid,
mdl_user.id as userid
FROM mdl_context
JOIN mdl_course_categories ON mdl_context.instanceid = mdl_course_categories.id
JOIN mdl_user ON mdl_course_categories.idnumber = mdl_user.idnumber
JOIN mdl_role ON mdl_role.shortname = 'manager'
WHERE mdl_context.contextlevel = 40
AND mdl_course_categories.depth > 1
AND NOT EXISTS (
SELECT mdl_role_assignments.id
FROM mdl_role_assignments
WHERE mdl_role_assignments.roleid = mdl_role.id
AND mdl_role_assignments.contextid = mdl_context.id
AND mdl_role_assignments.userid = mdl_user.id
AND mdl_role_assignments.itemid = 0
AND mdl_role_assignments.component = '')
Note that a duplicate is a combination of roleid, userid and contextid but also component and itemid. So component = '' needs to be checked too.
I have a master table called "parent" and a related table called "childs"
Now I run a query against the master table to update some values with the sum from the child table like this.
UPDATE master m SET
quantity1 = (SELECT SUM(quantity1) FROM childs c WHERE c.master_id = m.id),
quantity2 = (SELECT SUM(quantity2) FROM childs c WHERE c.master_id = m.id),
count = (SELECT COUNT(*) FROM childs c WHERE c.master_id = m.id)
WHERE master_id = 666;
Which works as expected but is not a good style because I basically make multiple SELECT querys on the same result. Is there a way to optimize that? (Making a query first and storing the values is not an option.
I tried this:
UPDATE master m SET (quantity1, quantity2, count) = (
SELECT SUM(quantity1), SUM(quantity2), COUNT(*)
FROM childs c WHERE c.master_id = m.id
) WHERE master_id = 666;
but that doesn't work.
Update: Here is the solution, thanks to everbody:
You can do something like this:
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = c.quantity1,
master.count = 1
If you have only one child record at a time. However if you want to use a group function like SUM() in the joined table that doesn't work. Either you get a "Invalid use of group function" if you leave the "group by" part or a "You have an error in your sql syntax if you use "GROUP BY c.master_id"
-- This doesnt work :(
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = SUM(c.quantity1),
master.count = COUNT(c.*)
GROUP by c.master_id
The solution is to use JOIN with a subquery:
UPDATE master m
INNER JOIN
(
SELECT master_id,
SUM(quantity1) as quantity1,
COUNT(*) as count
FROM childs c
GROUP BY master_id
) c
ON c.master_id = m.master_id
SET m.quantity1 = c.quantity1,
m.count = c.count
WHERE m.master_id = 666;
But since this pulls every row from the childtable the overhead would likely be bigger than using more subqueries like in the original sql. So you should add a WHERE clause to the joined table to get only the rows you need.
Another interesting approach is this syntax, which does the same as the JOIN with the WHERE clause but you should only use if if you want to update all rows with the same values and your subquery only returns one row, since the result from the subquery gets appended to the result and can be used like any column.
UPDATE master m,
(
SELECT SUM(c.quantity1) as sum_of_quantity,
COUNT(*) as rowcount FROM child c WHERE c.master_id = 666
) as c
SET m.quantity1 = c.sum_of_quantity,
m.count = c.rowcount
WHERE m.master_id = 666;
Rewriting Lieven's solution to MySQL:
UPDATE master m
JOIN (
SELECT master_id
, SUM(quantity1) as quantity1
, SUM(quantity2) as quantity2
, COUNT(*) as count
FROM childs c
GROUP BY
master_id
) c
ON c.master_id = m.master_id
SET
m.quantity1 = c.quantity1
,m.quantity2 = c.quantity2
,m.count = c.count
WHERE m.master_id = 666;
I don't know if it is allowed in MySQL, but SQL Server allows you to use the result of a select in an update.
UPDATE master m SET
quantity1 = c.quantity1
, quantity2 = c.quantity2
, count = c.count
FROM master m
INNER JOIN (
SELECT master_id
, quantity1 = SUM(quantity1)
, quantity2 = SUM(quantity2)
, count = COUNT(*)
FROM childs c
WHERE master_id = 666
GROUP BY
master_id
) c ON c.master_id = m.master_id
You could select your data into a temporary table, and then update using that data.
If you also want to insert "new" data in the same roundtrip, look into INSERT INTO ... SELECT FROM ... ON DUPLICATE KEY UPDATE ...
If you already are doing inserts if row doesn't exist, then that would be redundant with this example.
example:
INSERT INTO master m (id, quantity1, quantity2, count)
SELECT master_id, SUM(quantity1) q1, SUM(quantity2) q1, COUNT(*) c
FROM childs
GROUP BY master_id
ON DUPLICATE KEY UPDATE
m.quantity1 = q1,
m.quantity2 = q2,
m.count = c
NOTE! This is untested code, but I think it should be possible to backreference the select result in the UPDATE.
Syntax reference: http://dev.mysql.com/doc/refman/5.0/en/insert.html