Delete columns on couple of conditions - mysql

In a previous question I asked how I could sum up a total based on some conditions: Count total on couple of conditions
Suppose I have a table like this:
id col1 col2 col3
1 a 1 k1
2 a 2 k2
3 a -3 k3
4 b 3 k4
Now, when I get id=1, I want to delete all the rows where col1=a.
When I get id=4, I want to delete all the rows where col1=b.
How would I do this in SQL?
I tried based upon previous answer:
DELETE FROM table WHERE (col1) IN (SELECT col1 FROM table WHERE id = '1')
But that gave me an error: #1093 - You can't specify target table 'table' for update in FROM clause

This has been many times on stackowerflow, you cannot UPDATE/DELETE table with data from nested select on the same table. There're two ways to do this:
Load all data before (for example via php, sql procedure)
Create temporary table like the one you're using, clone data and use temporary table to select items

i have another suggested solution for this. What if you create a STORED PROCEDURE for this problem?
like this:
DELIMITER $$
CREATE PROCEDURE `DeleteRec`(IN xxx varchar(5))
BEGIN
DECLARE oID varchar(5);
SET oID := (SELECT col1 FROM table WHERE id = '1');
DELETE FROM table WHERE col1 = oID;
END$$
DELIMITER ;
do this helps you?

Related

Fill Column of SQL Table

I'm trying to fill a certain column of a SQL table with data from another table. I have a column named "size" in my table which should return the number of rows in the 2nd table where the id of both rows is the same. Is there a way to populate a SQL column based on a certain command? I would love to be able to fill the column based on this command:
SELECT count(*)
FROM second_table
WHERE id = "row_id";
Here is a sample database with the two tables:
Table 1
Name
id
tiger
1
lion
2
gazelle
1
Here is the desired output for Table 2:
id
Number of Animals
1
2
2
1
I am trying to fill the Number of Animals column but do it automatically and dynamically when another row is added or deleted to Table 1, which is why I want the Select count(*) SQL statement as the code for the column.
One method is a correlated subquery:
update table1 t1
set size = (select count(*)
from table2 t2
where t2.id = t1.id
);
If you need to do this dynamically (as data is inserted), then you would need to use a trigger. However, I would suggest that you calculate the value as needed, unless there is a specific reason why you need to store it.
I guess you need something like this:
CREATE TRIGGER UpdateAnimalCountTable2
AFTER INSERT ON `Table1` FOR EACH ROW
begin
DECLARE NewCount int;
SELECT count(1)
INTO #NewCount
FROM Table1
WHERE Table1.id= NEW.id;
UPDATE Table2
SET NoOfAnimals = #NewCount
WHERE id = NEW.id;
END;
Above is the trigger which will be executed after every insert in Table1 and will update the count in Table 2 for ID which just got inserted in Table1.

Automatic column value update in MySQL

Maybe I'm totally wrong and it's not pssible to do in MySQL. But, what I wanted to do is to fill out column row base in a select query:
For example:
Table 1:
IdNode NodeName NodeContact NodeStatus Nodegroup
1 Machine1 IT 1 IT
2 Machine2 IT 0 IT
3 Machine3 IT 1 IT
4 Machine4 IT 1 Others
4 Machine5 IT 1 Others
Table 2
IdGroup GroupName NodesManagedbyGroup
1 IT ??
2 others ??
Having those two tables, I would like to fill out (automatically) all rows in column NodesManagedbyGroup in the table2.
Manually it would be:
SELECT COUNT(*) FROM table1 where MemberOfGroup='IT';
result value Int = 3
Then
update table2 NodesManagedbyGroup = 3 where GroupName='IT';
There is any way that MySQL do it for me automatically
You can use triggers to do this - you'd create triggers for insert, update and delete on table 1 to update table 2.
This is generally a bad idea though - it's duplicating information around the database, denormalizing the schema.
Alternatively, you can create a view which calculates this data on the fly and behaves like a table when querying.
Use multiple UPDATE syntax with selecting counts in subquery as a sample:
UPDATE
table2
INNER JOIN
(SELECT COUNT(1) AS gcount, Nodegroup FROM table1 GROUP BY Nodegroup) AS counts
ON table2.GroupName=counts.Nodegroup
SET
table2.NodesManagedbyGroup=table1.gcount
You could set a job that performs a stored procedure every 15 minutes or so?

Make an sql value equal to another value from another table on insert

basically I have these both tables.
What I want to do is upon INSERTION of content in the second table (table 2) I want its value at NULL to be filled with the id from table 1 in which the pairs formed by part1/part2 from table 1 and part1/part2 from table 2 remain the same (please notice they can exchange between them). What is the best way to do this?
What you can do is create a trigger on Insert like below
CREATE TRIGGER grabIdFromTable1
BEFORE INSERT ON table2
FOR EACH ROW
BEGIN
SET NEW.id = (SELECT id FROM table1 WHERE part1 = NEW.part1
AND part2 = NEW.part2
);
END//
see this sqlFiddle

MySQL swap primary key values

The accepted answer to sql swap primary key values fails with the error Can't reopen table: 't' - presumably this has something to do with opening the same table for writing twice, causing a lock.
Is there any shortcut, or do I have to get both, set one of them to NULL, set the second one to the first one, then set the first one to the previously fetched value of the second?
Don't use temporary tables for this.
From the manual:
You cannot refer to a TEMPORARY table more than once in the same query.
For example, the following does not work:
mysql> SELECT * FROM temp_table, temp_table AS t2;
ERROR 1137: Can't reopen table: 'temp_table'
This error also occurs if you refer to a temporary table multiple
times in a stored function under different aliases, even if the
references occur in different statements within the function.
UPDATE:
Sorry if I don't get it right, but why does a simple three way exchange not work?
Like this:
create table yourTable(id int auto_increment, b int, primary key(id));
insert into yourTable(b) values(1), (2);
select * from yourTable;
DELIMITER $$
create procedure pkswap(IN a int, IN b int)
BEGIN
select #max_id:=max(id) + 1 from yourTable;
update yourTableset id=#max_id where id = a;
update yourTableset id=a where id = b;
update yourTableset id=b where id = #max_id;
END $$
DELIMITER ;
call pkswap(1, 2);
select * from yourTable;
To swap id values of 1 and 2, I would use a SQL statement like this:
EDIT : this does NOT work on an InnoDB table, only works on a MyISAM table, per my testing.
UPDATE mytable a
JOIN mytable b ON a.id = 1 AND b.id = 2
JOIN mytable c ON c.id = a.id
SET a.id = 0
, b.id = 1
, c.id = 2
For this statement to work, the id value of 0 must not exist in the table, any unused value would be suitable... but to get this to work in a single SQL statement, you need to (temporarily) use a third id value.
This solution works for regular MyISAM tables, not temporary tables. I missed that this was being performed on a temporary table, I was confused by the error message you reported Can't reopen table:.
To swap id values 1 and 2 in a temporary table, I'd run three separate statements, again, using a temporary placeholder value of 0:
UPDATE mytable a SET a.id = 0 WHERE a.id = 1;
UPDATE mytable b SET b.id = 1 WHERE b.id = 2;
UPDATE mytable c SET c.id = 2 WHERE c.id = 0;
Edit: Fixed errors

How to compare multiple parameters of a row column value?

how to write query for following request?
my table:
id designation
1 developer,tester,projectlead
1 developer
1 techlead
if id=1,designation="'developer'"
Then need to first,second records.Because 2 rows are having venkat.
if id=1,designation="'developer','techlead'" then need to get 3 records as result.
i wrote one service for inserting records to that table .so that i am maintaining one table to store all designation with same column with comas.
By using service if user pass id=1 designation="'developer','techlead'" then need to pull the above 3 records.so that i am maintaining only one table to save all designations
SP:
ALTER PROCEDURE [dbo].[usp_GetDevices]
#id INT,
#designation NVARCHAR (MAX)
AS
BEGIN
declare #idsplat varchar(MAX)
set #idsplat = #UserIds
create table #u1 (id1 varchar(MAX))
set #idsplat = 'insert #u1 select ' + replace(#idsplat, ',', ' union select ')
exec(#idsplat)
Select
id FROM dbo.DevicesList WHERE id=#id AND designation IN (select id1 from #u1)
END
You need to use the boolean operators AND and OR in conjunction with LIKE:
IF empid = 1 AND (empname LIKE '%venkat%' OR empname LIKE '%vasu%')
The above example will return all rows with empid equals 1 and empname containing venkat or vasu.
Apparently you need to create that query based on the input from user, this is just an example of how the finally query should look like.
Edit: Trying to do this within SqlServer can be quite hard so you should really change your approach on how you call the stored procedure. If you can't do this then you could try and split your designation parameter on , (the answers to this question show several ways of how to do this) and insert the values into a temporary table. Then you can JOIN on this temporary table with LIKE as described in this article.