Hi following are my 4 tables.
client_parent_question :-
+----+------------+------------+---------+-----+------+------+
| id | is_deleted | sort_order | version | cid | pid | qid |
+----+------------+------------+---------+-----+------+------+
| 1 | | 1 | 0 | 1 | 1 | 1 |
| 2 | | 2 | 0 | 1 | 1 | 2 |
| 3 | | 3 | 0 | 1 | 1 | 3 |
| 4 | | 4 | 0 | 1 | 1 | 4 |
| 5 | | 1 | 0 | 1 | 2 | 7 |
+----+------------+------------+---------+-----+------+------+
mysql> select * from client_parent;
+----+------------+------------+---------+-----+------+
| id | is_deleted | sort_order | version | cid | pid |
+----+------------+------------+---------+-----+------+
| 1 | | 1 | 0 | 1 | 1 |
| 2 | | 2 | 0 | 1 | 2 |
+----+------------+------------+---------+-----+------+
2 rows in set (0.00 sec)
mysql> select * from client_question;
+----+------------+---------+-----+------+------+
| id | is_deleted | version | cid | pqid | qtid |
+----+------------+---------+-----+------+------+
| 1 | | 0 | 1 | 1 | 1 |
| 2 | | 0 | 1 | 2 | 4 |
| 3 | | 0 | 1 | 2 | 4 |
| 4 | | 0 | 1 | 1 | 1 |
| 5 | | 0 | 1 | 2 | 4 |
| 6 | | 0 | 1 | 3 | 4 |
| 7 | | 0 | 1 | 3 | 4 |
| 8 | | 0 | 1 | 1 | 1 |
| 9 | | 0 | 1 | 2 | 4 |
| 10 | | 0 | 1 | 3 | 4 |
| 11 | | 0 | 1 | 4 | 4 |
| 12 | | 0 | 1 | 4 | 4 |
+----+------------+---------+-----+------+------+
mysql> select * from client_question_option;
+----+------------+---------+------+------+
| id | is_deleted | version | cqid | oid |
+----+------------+---------+------+------+
| 1 | | 0 | 2 | 1 |
| 2 | | 0 | 3 | 4 |
| 3 | | 0 | 6 | 2 |
| 4 | | 0 | 7 | 3 |
| 5 | | 0 | 11 | 1 |
| 6 | | 0 | 12 | 4 |
| 7 | | 0 | 14 | 1 |
| 8 | | 0 | 15 | 4 |
+----+------------+---------+------+------+
I know only cid and pid of client_parent table
My aim is to delete all from client_question,client_parent_question and client_question_option
In the client_question_option cqid id is the id of client_question table
Following is the sqlfiddle
I did
DELETE FROM cqo,qo,cpq client_question_option cqo ,client_question cq,client_parent_question ,client_parent cp
WHERE cqo.cqid=cq.id AND cq.pqid=pq.id AND cqo.oid=qo.id AND cq.cid=1 AND cp.pid=1
But this did not work.
You just need to move the FROM keyword after the table aliases. See multiple-table syntax
DELETE cqo, qo, cpq
FROM client_question_option cqo,
client_question cq,
client_parent_question,
client_parent cp
WHERE cqo.cqid=cq.id AND cq.pqid=pq.id AND cqo.oid=qo.id
AND cq.cid=1 AND cp.pid=1;
Your DELETE query's syntax is wrong, which must be somthing like this:-
DELETE cqo,cp,pq
FROM client_question_option cqo, client_question cq, client_parent_question pq, client_parent cp
WHERE cqo.cqid=cq.id AND cq.pqid=pq.id AND cqo.oid=cp.id AND cq.cid=1 AND cp.pid=1;
Hope this will help you.
using inner join
DELETE cqo,cq,cp,pq
FROM client_question_option cqo
INNER JOIN client_question cq
INNER JOIN client_parent_question as pq
INNER JOIN client_parent cp
WHERE cqo.cqid=cq.id AND cq.pqid=pq.id AND cqo.oid=cqo.id AND cq.cid=1 AND cp.pid=1
You have an option in MYSQL Called as ONDELETE CASCADE where in when you set this on a key
example : foreign key(cid) references client_parent(cid) ON DELETE CASCADE when you delete the key based on your condition all referencing ids will be deleted , so one simple query to delete parent row is enough for it to delete all child rows present in other table data
Advantages of using ON DELETE CASCADE
you are not require to right innerjoins and delete data manually
you dont get parent key errors
you can save up your time
Thats it NJOY!!!
Related
I have two tables users and features:
users
+----+-----------------+
| id | email |
+----+-----------------+
| 1 | test1#gmail.com |
| 2 | test2#gmail.com |
| 3 | test3#gmail.com |
| 4 | test4#gmail.com |
| 5 | test5#gmail.com |
+----+-----------------+
features
+------------+---------+---------------------+------------+
| feature_id | user_id | feature_name | can_access |
+------------+---------+---------------------+------------+
| 1 | 1 | automated-investing | 1 |
| 2 | 1 | crypto | 0 |
| 3 | 2 | crypto | 0 |
| 4 | 3 | automated-investing | 0 |
| 5 | 4 | automated-investing | 1 |
| 7 | 1 | financial-tracking | 1 |
| 8 | 2 | financial-tracking | 0 |
| 9 | 3 | financial-tracking | 1 |
| 10 | 4 | financial-tracking | 0 |
+------------+---------+---------------------+------------+
I am trying to get the id from users based on email and then create a new row in features using that id ,feature_name and can_access(feature_name and can_access are from a request).
I am able to do it but it is split into two parts and I am looking to do it with a single query.
Current query:
// Get ID from email
SELECT id FROM users WHERE email="test5#gmail.com";
// Insert values into features
INSERT INTO features(user_id, feature_name, can_access) VALUES(5,"crypto", 1);
Expected output:
+------------+---------+---------------------+------------+
| feature_id | user_id | feature_name | can_access |
+------------+---------+---------------------+------------+
| 1 | 1 | automated-investing | 1 |
| 2 | 1 | crypto | 0 |
| 3 | 2 | crypto | 0 |
| 4 | 3 | automated-investing | 0 |
| 5 | 4 | automated-investing | 1 |
| 7 | 1 | financial-tracking | 1 |
| 8 | 2 | financial-tracking | 0 |
| 9 | 3 | financial-tracking | 1 |
| 10 | 4 | financial-tracking | 0 |
| 11 | 5 | crypto | 1 |
+------------+---------+---------------------+------------+
INSERT INTO features (user_id, feature_name, can_access)
SELECT id, "crypto", 1 FROM users WHERE email="test5#gmail.com";
So instead of specifying the values, you use the select statement.
Edit
Please consider this before marking as duplicate
The common CTE or repeated joins or similar solutions does not fully satisfy the premise of the problem. Those solutions work for one and only one root (product) while the question at hand, asks for all roots within a table or query to be traversed and flattened, without a loop.
Problem Definition
I have three tables that define the characteristics of some products:
specifications
+----|------------------|----------|--------+
| id | name | type | status |
|----|------------------|----------|--------|
| 1 | height | float | 0 |
| 2 | width | float | 0 |
| 3 | length | float | 0 |
| 4 | weight | float | 0 |
| 5 | colour | int | 0 |
| 6 | material | int | 0 |
| 7 | manufacturer | int | 0 |
| 8 | durability | float | 0 |
| 9 | battery_type | int | 0 |
| 10 | battery_capacity | float | 0 |
| 11 | connectivity | set<int> | 0 |
| 12 | page | int | 0 |
| 13 | name | string | 0 |
| 14 | description | string | 0 |
+----|------------------|----------|--------+
groups
+----|-------------------|--------+
| id | name | status |
|----|-------------------|--------|
| 1 | cellphone | 0 |
| 2 | notebook | 0 |
| 3 | portable | 0 |
| 4 | workstation | 0 |
| 5 | pc | 0 |
| 6 | computer | 0 |
| 7 | electronic_device | 0 |
| 8 | book | 0 |
| 9 | sizeable | 0 |
| 10 | volumable | 0 |
| 11 | general | 0 |
+----|-------------------|--------+
specification_groups
+----|----------|------------------|--------+
| id | group_id | specification_id | status |
|----|----------|------------------|--------|
| 1 | 11 | 13 | 0 |
| 2 | 11 | 14 | 0 |
| 3 | 11 | 5 | 0 |
| 4 | 10 | 1 | 0 |
| 5 | 9 | 2 | 0 |
| 6 | 9 | 3 | 0 |
| 7 | 8 | 12 | 0 |
| 8 | 3 | 6 | 0 |
| 9 | 3 | 9 | 0 |
| 10 | 3 | 10 | 0 |
| 11 | 7 | 7 | 0 |
| 12 | 7 | 11 | 0 |
+----|----------|------------------|--------+
group_groups
+----|----------|--------------------|--------+
| id | group_id | group_reference_id | status |
|----|----------|--------------------|--------|
| 1 | 3 | 1 | 0 |
| 2 | 3 | 2 | 0 |
| 3 | 3 | 8 | 0 |
| 4 | 6 | 4 | 0 |
| 5 | 6 | 5 | 0 |
| 6 | 7 | 1 | 0 |
| 7 | 7 | 2 | 0 |
| 8 | 7 | 4 | 0 |
| 9 | 7 | 5 | 0 |
| 10 | 9 | 7 | 0 |
| 11 | 9 | 8 | 0 |
| 12 | 10 | 7 | 0 |
| 12 | 11 | 7 | 0 |
| 12 | 11 | 8 | 0 |
+----|----------|--------------------|--------+
product_groups
+----|--------|-------|--------+
| id | name | group | status |
|----|--------|-------|--------|
| 1 | phone1 | 1 | 0 |
| 2 | book1 | 8 | 0 |
+----|--------|-------|--------+
Ideally, I want to get all specification attributes for a product which the status along all tree-lines would be 0, but just to know what groups does a product is in is acceptable.
A result may look like this:
result
+---------|-------------|--------------|-------------------|----------|--------+
| row_num | product_id | product_name | product_group | group_id | status |
|---------|-------------|--------------|-------------------|----------|--------|
| 1 | 1 | phone1 | cellphone | 1 | 0 |
| 2 | 1 | phone1 | portable | 3 | 0 |
| 3 | 1 | phone1 | electronic_device | 7 | 0 |
| 4 | 1 | phone1 | sizable | 9 | 0 |
| 5 | 1 | phone1 | volumable | 10 | 0 |
| 6 | 1 | phone1 | general | 11 | 0 |
| 7 | 2 | book1 | book | 8 | 0 |
| 8 | 2 | book1 | portable | 3 | 0 |
| 9 | 2 | book1 | sizable | 9 | 0 |
| 10 | 2 | book1 | general | 11 | 0 |
+---------|-------------|--------------|-------------------|----------|--------+
Here's the answer if anyone else wants to do the same. The trick was to use the non-recursive initial selection parameters as constants in the recursive one:
with recursive
q as (
select * from product_groups as pg where ur.`status` = 0
)
, ancestors as (
(
select q.id as `product_id`, q.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg
join q on gg.group_id = q.group_id
where gg.`status` = 0
)
union
(
select q.id as `product_id`, q.product_name as `product_name`, null as `group_id`, q.group_id as `group_reference_id`
from q
)
union
(
select a.id as `product_id`, a.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg, ancestors as a
where gg.group_id = a.group_reference_id and gg.`status` = 0
)
)
select distinct
t.id as `product_id`, t.`group_id` as `group_id`, t.specification_id as `specification_id`, t.product_name as `product_name`, t.group_name as `group_name`, s.name as `specification_name`
from
(
select a.product_id, a.group_reference_id as `group_id`, sg.specification_id as `specification_id`, a.product_name, g.name as `group_name`
from ancestors as a
right join specification_groups as sg on a.group_reference_id = sg.group_id
where a.product_id is not null and sg.`status` = 0
) as t
join specifications as s on t.specification_id = s.id
order by product_id asc, group_id, asc, specification_id asc
;
My first data table is couponsnmaster
+-----------+----------+------------+
|couponsnid | couponid | couponsn |
+-----------+----------+------------+
| 1 | 1 | 1000 |
| 2 | 1 | 1001 |
| 3 | 1 | 1002 |
| 4 | 1 | 1003 |
| 5 | 1 | 1004 |
| 6 | 1 | 1005 |
+-----------+----------+------------+
My second data table is distribute
+-----------+--------------+--------------+--------------+
| distid | couponid | couponsnid | status |
+-----------+--------------+--------------+--------------+
| 1 | 1 | 1 | distribute |
| 2 | 1 | 2 | distribute |
| 3 | 1 | 3 | distribute |
| 4 | 1 | 1 | returned |
+-----------+--------------+--------------+--------------+
I want to fetch all "couponsn" from "couponsnmaster" with respect to "couponid" except status is " distribute" or "sold" or "bonus" in table "distribute"....
Try this query:
SELECT c.couponsn FROM
couponsmaster c INNER JOIN distribute d
ON c.couponsid = d.couponsid
WHERE d.status NOT IN('distribute','sold','bonus')
For example,I have 3 tables;
table1:
+-------+
| count |
+-------+
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
+-------+
table2:
+-------+
| count |
+-------+
| 3 |
| 0 |
| 0 |
| 0 |
| 0 |
+-------+
table3:
+-------+
| count |
+-------+
| 1 |
| 1 |
| 0 |
| 0 |
| 1 |
+-------+
I want to calculate table1.count+table2.count+table3.count, to get the result,table_right:
+-------+
| count |
+-------+
| 5 | (1+3+1=5)
| 1 | (0+0+1=1)
| 0 | (0+0+0=0)
| 0 | (0+0+0=0)
| 4 | (3+0+1=4)
+-------+
However, if I use command :
select table1.count+table2.count+table3.count as total
from table1,table2,table3;
The result will become to:
+-------+
| total |
+-------+
| 5 |
| 4 |
| 4 |
| 4 |
| 7 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 5 |
| 4 |
| 4 |
| 4 |
| 7 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 4 |
| 3 |
| 3 |
| 3 |
| 6 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 4 |
| 3 |
| 3 |
| 3 |
| 6 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 1 |
| 0 |
| 0 |
| 0 |
| 3 |
| 5 |
| 4 |
| 4 |
| 4 |
| 7 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
| 2 |
| 1 |
| 1 |
| 1 |
| 4 |
+-------+
This is not the result i want, If I try
select distinct table1.count+table2.count+table3.count as total
from table1,table2,table3;
I will get:
+-------+
| total |
+-------+
| 5 |
| 4 |
| 7 |
| 2 |
| 1 |
| 3 |
| 6 |
| 0 |
+-------+
Still isn't the result I want. How could i do to get table_right?
if you add a common id (lets call id rowId and lets assume it has the same name on every table),
SELECT t1.count + t2.count + t3.count AS total
FROM table1 AS t1
LEFT JOIN table2 AS t2 using (rowId)
LEFT JOIN table3 AS t3 using (rowId)
if you not have those ids, all i can think about its summing all t1 then all t2 then all t3 and finally add the results together.
SELECT t1+t2+t3 as total
FROM (SELECT (SELECT SUM(count) from table1) as t1,
(SELECT SUM(count) from table2) as t2,
(SELECT SUM(count) from table3) as t3
)
Check out this SQLFiddle
EDIT (2)
to add rowId just alter the tables:
ALTER TABLE table1 ADD COLUMN rowId int not null auto_increment primary key;
ALTER TABLE table2 ADD COLUMN rowId int not null auto_increment primary key;
ALTER TABLE table3 ADD COLUMN rowId int not null auto_increment primary key;
What is this self join and why do we need this self join?. I have till date never used self joins.
See if these links helps you...
http://www.udel.edu/evelyn/SQL-Class3/SQL3_self.html
http://awads.net/wp/2006/07/11/back-to-basics-self-joins/
http://www.sqltutorial.org/sqlselfjoin.aspx
Good Luck!!!
there are number of reasons, and tons of examples are available on web
http://www.udel.edu/evelyn/SQL-Class3/SQL3_self.html
mysql> SELECT * FROM pr WHERE id>80;
+----+------+--------+
| id | ids | status |
+----+------+--------+
| 81 | 4 | 4 |
| 82 | 2 | 3 |
| 83 | 2 | 4 |
+----+------+--------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM pr WHERE id<18;
+----+------+--------+
| id | ids | status |
+----+------+--------+
| 1 | 1 | 1 |
| 5 | NULL | 2 |
+----+------+--------+
2 rows in set (0.01 sec)
identical requests :
mysql> SELECT * FROM pr AS t1 ,pr AS t2 WHERE t1.id<18 AND t2.id>80;
+----+------+--------+----+------+--------+
| id | ids | status | id | ids | status |
+----+------+--------+----+------+--------+
| 1 | 1 | 1 | 81 | 4 | 4 |
| 5 | NULL | 2 | 81 | 4 | 4 |
| 1 | 1 | 1 | 82 | 2 | 3 |
| 5 | NULL | 2 | 82 | 2 | 3 |
| 1 | 1 | 1 | 83 | 2 | 4 |
| 5 | NULL | 2 | 83 | 2 | 4 |
+----+------+--------+----+------+--------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM pr AS t1 JOIN pr AS t2 ON t1.id<18 AND t2.id>80;
+----+------+--------+----+------+--------+
| id | ids | status | id | ids | status |
+----+------+--------+----+------+--------+
| 1 | 1 | 1 | 81 | 4 | 4 |
| 5 | NULL | 2 | 81 | 4 | 4 |
| 1 | 1 | 1 | 82 | 2 | 3 |
| 5 | NULL | 2 | 82 | 2 | 3 |
| 1 | 1 | 1 | 83 | 2 | 4 |
| 5 | NULL | 2 | 83 | 2 | 4 |
+----+------+--------+----+------+--------+
6 rows in set (0.00 sec)