Insert into w/ multiple selects giving ERROR 1242: Subquery returns more than 1 row - insert-into

I have table foo1 with columns UserID,TimeStamp; foo2 with columns userID,Level & table foo3 with columns userID,Timestamp.
I want to INSERT into foo1 all rows from foo3 where the UserID exists in table foo2.
I am getting ERROR 1242: Subquery returns more than 1 row with the following
INSERT into foo1 (UserID,TimeStamp)
SELECT
(SELECT UserID from foo2 as UserID),
(SELECT foo3.TimeStamp
from foo3
inner join foo2
ON foo3.UserID=foo2.UserID) as TimeStamp

If you want to INSERT into foo1 all rows from foo3 where the UserID exists in table foo2 then you should go through this:
INSERT into foo1 (UserID,TimeStamp)
SELECT foo3.UserID,foo3.TimeStamp
from foo3
inner join foo2
ON foo3.UserID=foo2.UserID

Related

MySQL- Update column with same id from different table by combining its values with same id

TableA
id
number
1
0
1
1
2
0
3
0
3
1
3
2
TableB
id
number2
1
2
3
I want to trigger update the TableB whenever TableA is updated.
Result should be
TableB
id
number2
1
0,1
2
0
3
0,1,2
The following statement display the result
select `id`,
group_concat(`number` separator ',')
from TableA
group by `id`
but I want to trigger update the TableB whenever TableA is updated.
(Optional): Only update the id which is updated will be preferred.
New workaround
CREATE TRIGGER `store_jan` AFTER UPDATE ON `TableA` FOR EACH ROW BEGIN
UPDATE `TableB`
SET number2 = group_concat(`number` separator ',') from TableA group by `id`
WHERE `TableB`.`id` = `TableA`.`id`
END
But showing error
Please help

Mysql fetch rows only contain a row with certain value

Lets say, my tables has the following rows:
id | prop1 | prop2
______________________
1 foo a
2 bar a
3 foo b
4 bar b
5 foo c
Now in this case, i want to get rows grouped by prop1 but ignore the groups that don't contain a row with prop2=c
So the intended result is:
1 foo a
3 foo b
5 foo c
Note, now there is only one group in the example but i want to be able to get all of them. How can i achieve this approach?
You can use exists clause to remove all the rows if it does not have prop2 = c using below query.
select *
from your_table t1
where
exists (select 1 from your_table t2 where t1.prop1 = t2.prop1
and t2.prop2 = 'c')
Explaination: Exists caluse will return true if it finds c for that group else false.
SELECT * FROM table WHERE prop2 != "c" GROUP BY prop1
This line is gonna delete att rows with C and the group everything else on prop1
Your expected result is not grouped by prop1. If it was grouped by prop1 then you would get only one record in the result.
To achieve the above, we can write a simple SELECT with sub-query, e.g.:
SELECT *
FROM table
WHERE prop1 IN (
SELECT prop1 FROM table WHERE prop2 = 'c'
);
The following query fetches all record with prop2 = 'c' (T1)
and joins them on all records (T2) that have an equal prop1:
select T2.*
from TABLE T1
join TABLE T2 ON T1.prop1=T2.prop1
WHERE T1.prop2 = 'c'
GROUP BY id

Join two tables by row

I have two tables with same column I need to merge that two table like below
Table1
id name
1 test1
4 test7
5 test9
6 test3
Table2
id name
2 test2
3 test5
6 test3
Result
id name
1 test1
2 test2
3 test5
4 test7
5 test9
6 test3
So I need to join/merge the two tables by id and you can see id 6 present in both table I need to override table 2 value and give above result. Kindly help me to solve the issue.
Thank you.
select id,name from table1
union
select id,name from table2 ;
other way
select * from (
select id,name from table1
union
select id,name from table2)temp order by temp.id ;
This will arrange records id wise
UNION will eliminate duplicate record , In your case it's id 6
When you want sorting then must be to create inner query like this
select * from
(
select id,name from table1 t1
union
select id,name from table2 t2
)a order by a.id ;

Selecting rows with multiple values from other rows with mySQL

Say I have the following table, named data:
ID foo1 foo2 foo3
1 11 22 33
2 22 17 92
3 31 33 53
4 53 22 11
5 43 23 9
I want to select all rows where either foo1, foo2 or foo3 match either of these columns in the first row. That is, I want all rows where at least one of the foos appears also in the first row. In the example above, I want to select rows 1, 2, 3 and 4. I thought that I could use something like
SELECT * FROM data WHERE foo1 IN (SELECT foo1,foo2,foo3 FROM data WHERE ID=1)
OR foo2 IN (SELECT foo1,foo2,foo3 FROM data WHERE ID=1)
OR foo3 IN (SELECT foo1,foo2,foo3 FROM data WHERE ID=1)
but this does not seem to work. I can, of course, use
WHERE foo1=(SELECT foo1 FROM data WHERE ID=1)
OR foo1=(SELECT foo2 FROM data WHERE ID=1)
OR ...
but that would invlove many lines, and in my real data set there are actually 16 columns, so it will really be a pain in the lower back. Is there a more sophisticated way to do so?
Also, what should I do if I want to count also the number of hits (in the example above, get 4 for row 1, 2 for row 4, and 1 for rows 2,3)?
SELECT data.*,
(data.foo1 IN (t.foo1, t.foo2, t.foo3))
+ (data.foo2 IN (t.foo1, t.foo2, t.foo3))
+ (data.foo3 IN (t.foo1, t.foo2, t.foo3)) AS number_of_hits
FROM data JOIN data t ON t.id = 1
WHERE data.foo1 IN (t.foo1, t.foo2, t.foo3)
OR data.foo2 IN (t.foo1, t.foo2, t.foo3)
OR data.foo3 IN (t.foo1, t.foo2, t.foo3)
See it on sqlfiddle.
Actually, on reflection, you might consider normalising your data:
CREATE TABLE data_new (
ID BIGINT UNSIGNED NOT NULL,
foo_number TINYINT UNSIGNED NOT NULL,
val INT,
PRIMARY KEY (ID, foo_number),
INDEX (val)
);
INSERT INTO data_new
(ID, foo_number, val)
SELECT ID, 1, foo1 FROM data
UNION ALL SELECT ID, 2, foo2 FROM data
UNION ALL SELECT ID, 3, foo3 FROM data;
DROP TABLE data;
Then you can do:
SELECT ID,
MAX(IF(foo_number=1,val,NULL)) AS foo1,
MAX(IF(foo_number=2,val,NULL)) AS foo2,
MAX(IF(foo_number=3,val,NULL)) AS foo3,
number_of_hits
FROM data_new JOIN (
SELECT d1.ID, COUNT(*) AS number_of_hits
FROM data_new d1 JOIN data_new d2 USING (val)
WHERE d2.ID = 1
GROUP BY d1.ID
) t USING (ID)
GROUP BY ID
See it on sqlfiddle.
As you can see from the execution plan, this will be considerably more efficient for large data sets.
There are several ways to get the result set.
Here's one approach, (if you don't care about which fooN gets matched with with fooN, and also want to return that "first" row).
SELECT DISTINCT d.*
JOIN ( SELECT foo1 AS foo FROM data WHERE id = 1
UNION ALL
SELECT foo2 FROM data WHERE id = 1
UNION ALL
SELECT foo3 FROM data WHERE id = 1
) f
JOIN data d
ON f.foo IN (d.foo1, d.foo2, d.foo3)
That ON clause could also be written like this:
ON d.foo1 = f.foo
OR d.foo2 = f.foo
OR d.foo2 = f.foo
To get a "count" of the hits...
SELECT d.id
, d.foo1
, d.foo2
, d.foo3
, SUM( IFNULL(d.foo1=f.foo,0)
+IFNULL(d.foo2=f.foo,0)
+IFNULL(d.foo3=f.foo,0)
) AS count_of_hits
JOIN ( SELECT foo1 AS foo FROM data WHERE id = 1
UNION ALL
SELECT foo2 FROM data WHERE id = 1
UNION ALL
SELECT foo3 FROM data WHERE id = 1
) f
JOIN data d
ON f.foo IN (d.foo1, d.foo2, d.foo3)
GROUP
BY d.id
, d.foo1
, d.foo2
, d.foo3
eggyal is right, as usual. Getting the count of hits is actually much simpler: we can just use a SUM(1) or COUNT(1) aggregate, no need to run all those comparisons, we've already done all the necessary comparisons.
SELECT d.id
, d.foo1
, d.foo2
, d.foo3
, COUNT(1) AS count_of_hits
JOIN ( SELECT foo1 AS foo FROM data WHERE id = 1
UNION ALL
SELECT foo2 FROM data WHERE id = 1
UNION ALL
SELECT foo3 FROM data WHERE id = 1
) f
JOIN data d
ON f.foo IN (d.foo1, d.foo2, d.foo3)
GROUP
BY d.id
, d.foo1
, d.foo2
, d.foo3

MySQL Delete duplicates in consecutive rows

Suppose this table:
ID ColA ColB
1 7 8
2 7 9
3 7 9
4 5 8
5 6 9
6 6 9
7 5 4
The PK is the ID coumn.
Now, I want to delete all duplicates of ColA and ColB in consecutive rows.
In this example rows 2,3 and 5,6 contain duplicates.
These shall be removed so that the higher ID is remained.
The output should be:
ID ColA ColB
1 7 8
3 7 9
4 5 8
6 6 9
7 5 4
How can this be done with mySQL?
Thanks,
Juergen
SELECT
ID
FROM
MyTable m1
WHERE
0 < (SELECT
COUNT(*)
FROM
MyTable m2
WHERE
m2.ID = m1.ID - 1 AND
m2.ColA = m1.ColA AND
m2.ColB = m1.ColB)
and then you can use a
delete from MyTable where ID in ...
query. This way it would surely work in any version.
CREATE TEMPORARY TABLE duplicates (id int primary key)
INSERT INTO duplicates (id)
SELECT t1.id
FROM table t1
join table t2 on t2.id = t1.id + 1
WHERE t1.ColA = t2.ColA
and t1.ColB = t2.ColB
-- SELECT * FROM duplicates --> are you happy with that? => delete
DELETE table
FROM table
join duplicates on table.id = duplicates.id
Depending on how many records you have, this might not be the most efficient:
SELECT (SELECT TOP 1 id FROM table WHERE colA = m.colA AND colB = m.colB ORDER BY id DESC) AS id, m.*
FROM (SELECT DISTINCT colA, colB
FROM table) m
There might be syntax errors because I usually use mssql, but the idea should be similar.
I've called the first table 'test'.
Firstly create a table that will hold all the identical combinations of ColA and ColB:
create temporary table tmpTable (ColA int, ColB int);
insert into tmpTable select ColA,ColB from test group by ColA, ColB;
Now, select the maximum id in the original table for each identical combination of ColA and ColB. Put this into a new table (called idsToKeep because these are the rows we do not want to delete):
create temporary table idsToKeep (ID int);
insert into idsToKeep select (select max(ID) from test where test.ColA=tmpTable.ColA and test.ColB=tmpTable.ColB) from tmpTable;
Finally, delete all the entries from the original table that are not in the idsToKeep table:
delete from test where ID <> all (select ID from idsToKeep);