MySQL get parents with the same id and related child - mysql

Let say we have an mysql table
Id RelatedId
1 0
2 0
3 1
4 2
5 1
6 2
How can I delete all records with RelatedId=0 and then childs on Id=RelatedId in a single MySQL query?

The alterative to ClaireG's answer is to enforce the relationship with foreign keys set to ON DELETE CASCADE.

You have to check it twice:
DELETE FROM [yourTableName]
WHERE RelatedId = 0
OR (RelatedId in
(select id from [yourTableName] where RelatedId = 0))
Find all the records where relatedID is null, and find all other ids that are related to 0 (in your case [1,2])

seems that works...
DELETE
FROM
delete_table
WHERE
delete_table.RelatedId IN (
select Id from(
SELECT
s1.Id
FROM
delete_table s1
WHERE
s1.RelatedId = 0
) as x
)
OR delete_table.RelatedId = 0;

DELETE TABLENAME
FROM TABLENAME T1
WHERE TABLENAME.ID = T1.RELTED_ID AND T1.RELTED_ID = 0;

Related

Avoid duplicates on MySQL update

I have a many-to-many relation table like this
element_a
element_b
1
2
1
3
2
1
2
3
3
1
3
3
I want to replace element_a with id 2 by id 1
UPDATE mytable x
SET x.element_a = 1
WHERE x.element_a = 2;
Since there is an unique index on (element_a, element_b ), this will result with duplicates error.
How can I execute my query without MySQL Error 1062 ?
You can use an update with LEFT JOIN:
UPDATE mytable x
LEFT JOIN mytable t ON t.element_b = x.element_b AND 1 = t.element_a
SET x.element_a = 1
WHERE
x.element_a = 2 AND t.element_a IS NULL
If t.element_a IS NOT NULL then pair element_a, element_b already exists in your table. Thus adding t.element_a IS NULL in the WHERE clause prevents UPDATE in case of duplicates.
Demo here

Please give some approach to achieve the data set for the following data set

In my table there is 5 distinct event 1,2,3,4,5. In attendee column there are attendees who attained these events. and in isThisuserHost column there is 0 and 1 flag. 1 for host who host the event and 1 for attendee who attain the event.I need to show the event where host is 2 and attendee is 4. In this table we can see that event 1,2,and 4 is those rows where host is 2 and attendee is 4. How to extract the result using a single query?
Try the following query:
select distinct eventid
from mytable m1
where 2 in (select attendee
from mytable m2
where m2.eventid = m1.eventid
and isTheuserHost = 1
)
and 4 in (select attendee
from mytable m3
where m3.eventid = m1.eventid
and isTheuserHost = 0
)
You need a selfjoin here:
select h.eventId
from myTable h
join myTable a using(eventId)
where h.isTheuserHost = 1
and a.isTheuserHost = 0
and h.attendee = 2
and a.attendee = 4
h and a are different aliases for the same table. h stands for hoster and a for anttendee with the corresponding condition for the isTheuserHost column. Then you can use that table as if it were two.

SQL - Get boolean values for each matching field

I need help with SQL request.
I have 3 tables:
Table User
id name
1 Jon
2 Jack
3 Bill
Table Type
id name
1 View
2 Edit
3 Delete
Table Right
id user type
1 1 1
2 1 2
3 1 3
4 2 1
5 3 1
So table Right contains linked pairs of user-type. I need a request which gets user name, and a boolean (BIT) value for each enrty in table Type, which exists in Right table for this user. Something like this for my example tables:
Username View Edit Delete
Jon 1 1 1
Jack 1 0 0
Bill 1 0 0
Thank you very much in advance!
untested:
select name,
coalesce(select 1 from `right` where `type` = 1 and right.user = user.id, 0) as `View`,
coalesce(select 1 from `right` where `type` = 2 and right.user = user.id, 0) as `Edit`,
coalesce(select 1 from `right` where `type` = 3 and right.user = user.id, 0) as `Delete`
from User
Alternatively:
select name, coalesce(RVIEW.R, 0) as `View`, coalesce(REDIT.R, 0) as `Edit`, coalesce(RDEL.R, 0) as `Delete`
from User
left join (select 1 R from `right` where `type` = 1) RVIEW on (right.user = user.id)
left join (select 1 R from `right` where `type` = 2) REDIT on (right.user = user.id)
left join (select 1 R from `right` where `type` = 3) RDEL on (right.user = user.id)
In your example, you are using reserved words as table names.
If you want to learn more about naming conventions for table names, have a look at the links in an earlier question on Stack Overflow here
Example below shows yet another way of getting the data you want (with other names for the tables):
select person.name as Username
, max( if( person_right.type_id = 1, 1, 0 ) ) as `View`
, max( if( person_right.type_id = 2, 1, 0 ) ) as `Edit`
, max( if( person_right.type_id = 3, 1, 0 ) ) as `Delete`
from person
left outer join person_right
on person_right.user_id = person.id
group by person.name
order by person.id
Another thing that might be worth looking at is the datamodel,
because Rights are normally quite "fixed".
If anyone accidentally changes one of the names in the Type table, you might have a serious security issue.
What you can do is change the person_right table to look like this
windowid user_id view_access edit_access delete_access
1 1 1 1 1
1 2 1 0 0
1 3 1 0 0
where the primary key would be window_id+user_id allowing you to setup different rights per user in a particular window/part of your application.
Hope this helps.

row dependant variables in mysql query

I have a mysql database as follows. I am using it with phpmyadmin.
id time_came time_exit
0 2 3
1 3 5
5 5 1
7 1 10
9 1 8
I want another column as "wait" with the following logic,
foreach(i in time_came){
wait=count(time_came<i&&i<time_exit)
}
So then each column has a "wait" value too. I can do this with php. But I need to do this with mysql. I am confusing because "i" is varying for each row?
Thanks in advance.
Is this what you want?
select t.*,
(select count(*)
from table t2
where t2.time_came between t.time_came and t2.time_came < t.time_exit
) as wait
from table t;
EDIT:
To do the update, you need to use join:
update table t join
(select t.id,
(select count(*)
from table t2
where t2.time_came between t.time_came and t2.time_came < t.time_exit
) as wait
from table t
) as newval
on t.id = newval.id
set t.wait = newval.wait

MySQL case-when-then (or other ways) to check values of multiple rows

I request some help with MySQL when-then statement to fetch all the sid from the table after comparing multiple records having same sid but different cid-data values:
flag sid cid data
---- --- --- ----
1 300 1 john
1 300 2 john_email
1 300 3 77500
1 300 4 ok
1 301 1 jack
1 301 2 john_email
1 301 3 72210
1 301 4 notok
Here for each sid, I need to check if (sid=2 has data=john_email) AND (sid=4 has data=ok)
Only if both the conditions are satisfied, I return the sid. i.e. the output will be '300' only.
I am confused how to use the case-when-then and compare 'data' with 'john_email' and also compare data with 'ok' ... based on the cid values. Thanks for reading.
try
select sid
from your_table
group by sid
where (cid=2 and data='john_email')
or (cid=4 and data='ok')
having sum(cid=2)=1 and sum(data='john_email')=1
and sum(cid=4)=1 and sum(data='ok')=1
SQLFiddle example
You should join the table to itself, then you can check the condition in the two rows as if it was one row...
SELECT T1.sid
FROM MYTABLE T1
JOIN MYTABLE T2 ON T1.SID=T2.SID AND T1.CID=1 AND T2.CID=4
WHERE T1.DATA='john'
AND T2.DATA='ok'
Note that I used the CID values in the join clause, but you will have to adjust them if you want to join on different data rows...
What you can do is use a subquery and check if the value exists.
SELECT
*
FROM
table outertable
WHERE
( cid=2 AND data='john_email' )
AND
EXISTS ( SELECT sid FROM table WHERE cid = 4 AND data = 'ok' AND sid = outertable.sid )