Set with select clause fail - mysql

I have a table 1 that contains many entities and another one (table 2) that has 2 columns : the primary key of table 1 and a second column. An entity in table 1 has several other entities (from table 1 too) assigned by the second column in table 2
example:
id | type | ownerId
1 | bigObject | 1
2 | littleObj | 3
3 | littleObj | 3
id | key
1 | 2
1 | 3
and I want to update the ownerId of all littleObjects to the ownerId of the big objects.
What I tried:
UPDATE entity
SET ownerid = (SELECT ownerid
FROM entity
WHERE id = 1)
WHERE id IN (SELECT key
FROM table_b
WHERE id = 1)
;
But it says You can’t specify target table ‚entity‘ for update in FROM clause

You must be using MySQL, because that generates the error. Use this form instead:
UPDATE entity e CROSS JOIN
(SELECT ownerid
FROM entity
WHERE id = 1
) e1
SET e.ownerid = e1.ownerid
WHERE id IN (SELECT key
FROM table_b
WHERE id = 1)

Related

How to get distinct id based on the order of increasing times of ID in MYSQL

How to get the distinct id from a group of id based on the order of increasing number of times it present.
For Example , input: 3,1,1,2,2,2
Here id 2 present 3 times , id 1 present 2 times and id 3 present 1 time..
here is my output 2,1,3
How to get these with a single query using mysql
select distinct id, COUNT(id) from your_table
group by id
order by COUNT(id)
heres a simple query with the count as well if you want to check its in the correct order.
At first, we need to analyse how you have got this input:
3,1,1,2,2,2
The CSV input can be pre-filtered, if it is through:
User Input
Query Output
If it was a User Input, then there's no way MySQL can directly access the value, unless it is stored as data. In that case, you will be having some kind of PHP or other programming language that sends the data to MySQL. So, assuming it for PHP, what I would do is:
<?php
$csv = "3,1,1,2,2,2";
$arr = explode(",", $csv);
$arr = array_unique($arr);
?>
Now you will have unique values.
If it was a query output, you just need to use DISTINCT keyword.
SELECT DISTINCT(`id`) FROM `table` WHERE `SomeCondition`='Value';
You can also try by using GROUP BY, but using DISTINCT is much faster IMHO. (What's faster, SELECT DISTINCT or GROUP BY in MySQL?)
Suppose we have 2 tables with us:
1) student: Fields are as follows:
a) id: INTEGER AUTO INCREMENT PRIMARY KEY
b) name: VARCHAR
Sample Data:
student
id | name
----------
1 | A
2 | B
3 | C
2) marks: Fields are as follows:
a) id: INTEGER AUTO INCREMENT PRIMARY KEY
b) sid: INTEGER FOREIGN KEY (refers to id field from student table)
c) subject: VARCHAR
d) marks: INTEGER
Sample Data:
marks:
id | sid | subject | marks
--------------------------
1 | 1 | s1 | 40
2 | 2 | s2 | 50
3 | 2 | s1 | 60
4 | 2 | s2 | 70
5 | 3 | s1 | 80
Use below query to get distinct student id's with referring records in descending order:
SELECT `student`.`id`, COUNT(*) AS `total` FROM `student` INNER JOIN `marks` ON (`student`.`id` = `marks`.`sid`) WHERE 1 GROUP BY `student`.`id` ORDER BY `total` DESC
You can use group by to get unique ids.
SQL Query:
select id from table group by id;

Get records from table 1 and join it from another table when the table 2 value does not exist

1st Table - explore_offers:
- id
- Primary Key - offer_unique
2nd Table - participated_explore_offers:
- id
- email - user_email
- Primary Key - offer_unique
What i want:
* Show 1st Table records, and exclude those records, which are in the 2nd table with a specific email found
ex:
SELECT eo.*
, peo.user_email
FROM explore_offers eo
LEFT
JOIN participated_explore_offers peo
ON eo.offer_unique = peo.offer_unique
WHERE peo.user_email = 'test#gmail.com'
I've tried that example, and i'm getting 0 records.
I have 2 records in the first table, and one in the second table, and the result i want is:
*. get that one record from the first table, where this record does NOT exist in the second table.
1st Table content:
Nr id Primary Key
1 0 m1
2 1 m2
2nd Table Content
Nr id user_email Primary Key
1 0 test#gmail.com m1
1 0 test2#gmail.com m2
Expected
Nr id Primary Key
1 1 m2
What i had:
0 Records
SQL DEMO
Try this :
select * from explore_offers
where offer_unique not in
(select offer_unique from participated_explore_offers where user_email='test#gmail.com')
Move the email filteration to the JOIN condition to make it work with LEFT JOIN:
SELECT eo.*,peo.user_email
FROM explore_offers eo
LEFT JOIN participated_explore_offers peo ON (eo.offer_unique = peo.offer_unique)
AND peo.user_email = 'test#gmail.com'
WHERE peo.user_email is null;
demo:
| Nr | id | offer_unique | user_email |
|----|----|--------------|------------|
| 2 | 1 | m2 | (null) |

Join on multiple tables

I have 2 SQL tables:
select * from operation;
id | name
----+--------------------
1 | Account add
2 | Account edit
select * from role_operation;
id | role | operation
----+----------+-----------
1 | admin | 1
2 | operator | 1
3 | admin | 2
The id column in operation table and the operation column in role_operation are linked. (Foreign key). How can I get all rows where operation name = Account add
I tried SELECT role_operation.role, operation.name FROM role_operation INNER JOIN operation ON role_operation.operation=operation.id;
But this gives me all the rows which have an operation id present in the operation field of role_operation table.
use where
SELECT role_operation.role, operation.name
FROM role_operation
INNER JOIN operation ON role_operation.operation=operation.id
where operation.name = 'Account add';
SELECT role_operation.role, operation.name FROM role_operation
INNER JOIN operation on operation.id = role_operation.operation
WHERE operation.name='Account add'

Update all rows associated to duplicates of another table

MySQL 5.6
We have two tables: cars and views.
Cars Views
---+------- ---+-------
id | desc id | car_id
---+------- ---+-------
1 | desc1 1 | 1
2 | Desc1 2 | 2
3 | desc2 3 | 3
The problem is with the desc field in the table cars. That row had to be unique but we unfortunately allowed the users to fill in uppercased values, which brought us to the situation of having (according to the example above) two duplicated rows: desc1 and Desc1.
The way to fix that is DELETE the duplicated cars, and keep only the first one. We know how to deal with that.
Our problem comes before that, when updating the related table, where some views are associated to a car which has a duplicated desc (for instance a car which is going to be removed). Those views should be updated for being assigned to the first of the duplicated cars (in this case the car id #1)
After the UPDATE, we'd like this result in views:
Views
---+-------
id | car_id
1 | 1
2 | 1
3 | 3
We are able to get all the ids of the duplicated cars and deal with the deletion but we're stuck with this UPDATE.
The solution will be to create a mapping table with before/after values for description ids.
The result should look something like:
Before | After
---------------
1 | 1
2 | 1
3 | 3
That table can be created with something like this:
SELECT
cars.id AS before_id,
fixed.lowest_id AS after_id
FROM cars
JOIN (
-- The lowest id value for each duplicate description
SELECT
MIN(id) AS lowest_id,
LOWER(desc) AS lower_desc
FROM cars
GROUP BY LOWER(desc)
) fixed
ON LOWER(cars.desc) = fixed.lower_desc
You can then have your views match to that mapping table to pull the new "correct" id value.
UPDATE Views AS v
JOIN (SELECT c1.id AS oldID, MIN(c2.id) AS newID
FROM Cars AS c1
JOIN Cars AS c2 ON LOWER(c1.desc) = LOWER(c2.desc)
HAVING oldID != newID) AS c
ON v.car_id = oldID
SET v.car_id = newID
The subquery finds the primary ID for each ID that contains a duplicate description. Joining this with the Views table provides the information needed to make the replacements.

MySQL: Merge tables, run SELECT and update duplicates

I've the following three tables:
Table A:
id VARCHAR(32) | value VARCHAR(32) | groupId INT
abcdef | myValue1 | 1
ghijkl | myValue2 | 2
mnopqr | myValue3 | 1
Table B:
id VARCHAR(32) | value VARCHAR(32) | userId INT
abcdef | myValue4 | 1
uvwxyz | anotherValue | 1
Table C:
id VARCHAR(32) | someOtherColumns...
abcdef
ghijkl
mnopqr
...
uvwxyz
Table A and B are used for a m:n-association, thus the "id"-column in both tables references the same field ("id"-column in table c).
What I want to do is (for instance)... select all entries in table A where groupId = 1
SELECT * FROM TableA WHERE groupId = 1
and also select all entries in table B where userId = 1
SELECT * FROM TableB WHERE userId = 1
That's all no problem... but the following makes the select-statement(s) difficult: How can I merge both select-results and replace the value of the first result? For example:
selecting all entries in Table A where groupId = 1 I'll get abcdef and also mnopqr.
when I select all entries in Table B where userId = 1 I'll also get abdef (and additionally uvwxyz).
Now, the value of abcdef in Table B should replace the value in the selection result of table A. And the uvwxyz-entry should be added to the result.
Finally I'm looking for a query which produces the following table:
id VARCHAR(32) | value VARCHAR(32)
abcdef | myValue4 -- myValue1 from the select-statement in tableA should be overwritten
mnopqr | myValue2 -- from table A
uvwxyz | anotherValue -- from table B
I hope anyone know how to do this... thanks in advance for any suggestion! By the way... it would be great if there is any chance to realize this using one single (long) select statement.
Try this:
SELECT * FROM TableB WHERE userId = 1
UNION
SELECT * FROM TableA WHERE groupId = 1
and id not in (select id from TableB where userid = 1)
#rs points out to use the UNION, which is required since MySQL doesn't have FULL joins.
Favoring the data from table B is a chose for CASE:
select id, case when max(value_b) is not null then max(value_b) else max(value_a) end as final_value
from (
select id, value as 'value_a', null as 'value_b' from tableA
union
select id, null, value from tableB
) ugh
group by 1;