How to insert text with a value from another table - mysql

I am trying to insert a text with a value from another table, can it be done in one query?
if I remove ('value from table2 : ' +) from the query, the value selected is inserted properly, but when I add it, the value inserted is 0.
INSERT INTO table1 ( col1, col2, col3, col4)
VALUES ( 896, 'azer', 'value from table2 : ' + (SELECT table2.col2 FROM table2 WHERE table2.col1 = 5 ), 675)
the inserted value in col3 should like this: "value from table2 : zsqd"

You need to use CONCAT function for concatenation.
INSERT INTO table1 ( col1, col2, col3, col4)
VALUES ( 896, 'azer', (SELECT CONCAT('value from table2 :',table2.col2) FROM table2 WHERE table2.col1 = 5 ), 675)

Very simple
If col3 in table1 is varchar or text then try this
INSERT INTO table1 ( col1, col2, col3, col4)
VALUES ( 896, 'azer', (SELECT CONCAT("value from table2 : ",table2.col2) FROM table2 WHERE table2.col1 = 5 ), 675)

Related

Delete using group by with multiple columns

I want to delete all the rows which are returned by this query.
SELECT col1, col2, col3 FROM myTable GROUP BY col1, col2, col3 HAVING count(*) > 1;
I tried this, but it gives me a syntax error.
DELETE FROM myTable WHERE col1, col2, col3 IN (
SELECT col1, col2, col3 FROM (
SELECT col1, col2, col3 FROM myTable
GROUP BY col1, col2, col3 HAVING count(*) > 1 )
t );
Use an INNER JOIN with your table
DELETE t1 FROM myTable t1
INNER JOIN (
SELECT col1, col2, col3 FROM (
SELECT col1, col2, col3 FROM myTable
GROUP BY col1, col2, col3 HAVING count(*) > 1 )
t )
t2 ON t2.rcol1 = t1.rcol1 AND t2.col2 = t1.col AND t2.col3 = t1.col3;
But you you should test it on a test database, because i don't think that your select identifies the right rows, better would be to have a UNIQUE column, that would identify the correct rows, because this would delete all rows

MySQL Removing duplicates based on condition and multiple columns combinations

I have a table in MySQL as below:
ID, COL1, COL2 VALUE
'1', 'OBJ1', 'OBJ2', '5'
'2', 'OBJ1', 'OBJ2', '1'
'3', 'OBJ2', 'OBJ1', '3'
'4', 'OBJ3', 'OBJ1', '4'
'5', 'OBJ3', 'OBJ4', '6'
Relation between col1 and col2 is independent of position, ie OBJ1 in col1 and OBJ2 in col2 is same as OBJ1 in col2 and OBJ2 in col1. This means that OBJ1 and OBJ2 shares a relationship.
Now, this means that the object OBJ1 and OBJ2 have a value of 1,5,3...
I want to keep only distinct values ie OBJ1, OBJ2 should occur only once in the table, not even OBJ2,OBJ1.
Importantly, I want to retain only the row with HIGHEST value.
The result I want is thus:
ID, COL1, COL2 VALUE
'1', 'OBJ1', 'OBJ2', '5'
'4', 'OBJ3', 'OBJ1', '4'
'5', 'OBJ3', 'OBJ4', '6'
What is the best and efficient way of doing this? I have over 10 million rows.
I have searched in many forums/Google but cannot find the exact answer I am looking for..
Try this:
SELECT t1.ID, t1.COL1, t1.COL2, t1.VALUE
FROM mytable AS t1
JOIN (
SELECT LEAST(COL1, COL2) AS C1,
GREATEST(COL1, COL2) AS C2,
MAX(VALUE) AS max_Value
FROM mytable
GROUP BY LEAST(COL1, COL2),
GREATEST(COL1, COL2)
) AS t2 ON t1.COL1 = t1.C1 AND t1.COL2 = t2.C2 AND t1.VLAUE = t2.max_Value
You could use an in clause and subselect grouped by
for solve also the problem related to the distinct pair combination
You should organize the data in a proper way
select
id
, case when col1 <= col2 then col1 else col2 end COL1
, case when col1 > col2 then col1 else col2 end COL2
, value
from start_table
then the query became
SELECT t1.ID, t1.COL1, t1.COL2, t1.VALUE
FROM (
select
id
, case when col1 <= col2 then col1 else col2 end COL1
, case when col1 > col2 then col1 else col2 end COL2
, value
from start_table
) t1
where value in (
select max(value)
FROM (
select
id
, case when col1 <= col2 then col1 else col2 end COL1
, case when col1 > col2 then col1 else col2 end COL2
, value
from start_table
) mytable
group by col1, col2
)
or using an inner join
SELECT t1.ID, t1.COL1, t1.COL2, t1.VALUE
FROM (
select
id
, case when col1 <= col2 then col1 else col2 end COL1
, case when col1 > col2 then col1 else col2 end COL2
, value
from start_table
) t1
inner join
(
select max(value) as value
FROM (
select
id
, case when col1 <= col2 then col1 else col2 end COL1
, case when col1 > col2 then col1 else col2 end COL2
, value
from start_table
) mytable
group by col1, col2
) T2 on t1.value = t2.value
Rebuild the table so that no dups are allowed; in the process, get rid of the dups. (And get rid of the apparently useless id.)
CREATE TABLE new (
col1 ...,
col2 ...,
`value` ...,
PRIMARY KEY(col1, col2),
INDEX(col2, col2, `value`)
) ENGINE=InnoDB;
INSERT INTO new (col1, col2, `value`)
SELECT LEAST(col1, col2),
GREATEST(col1, col2),
`value`
ON DUPLICATE KEY UPDATE
`value` := GREATEST(`value`, VALUES(`value`));
RENAME TABLE real TO old,
new TO real;
DROP TABLE old;
In the future, you will need this for INSERTing/UPDATEing new rows:
INSERT INTO new (col1, col2, `value`)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
`value` := GREATEST(`value`, VALUES(`value`));
(This assumes you want to increase value whenever it is already in the table.)
These save space and speed (important for 10M rows): Getting rid of id; having optimal indexes; using InnoDB; etc.

How to use a sub-query as value for inserting?

I have a query like this:
INSERT INTO table1(col1,col2,col4)
VALUES (1, (select col1 from table2 where col2 = :param), 1);
The above query works as well. Now I want to use two columns from table2, like this:
INSERT INTO table1(col1,col2,col3,col4)
VALUES (1, (select col1,col2 from table2 where col2 = :param), 1);
But second query doesn't work, How can I fix it?
INSERT INTO table1(col1, col2, col3, col4)
select 1, col1, col2, 1
from table2
where col2 = :param;

Insert into table select where not exists affecting 0 rows

I'm trying to insert into a table with the following syntax:
INSERT INTO table1(
col1, col2, col3)
SELECT distinct
col1, col2, getDate()
FROM table2 WHERE NOT EXISTS(
SELECT 1 FROM table1, table2
WHERE ((table1.col1 = table2.col1) or (table1.col1 is null and table2.col1 is null))
AND ((table1.col2 = table2.col2) or (table1.col2 is null and table2.col2 is null)))
But when I run the query, it shows (0 row(s) affected).
The SELECT statement within the NOT EXISTS statement returns the correct number of rows that I don't want inserted. If I try to insert into the table without the WHERE NOT EXISTS statement, it inserts everything. I only want to insert rows that are not already in table1.
Try this:
INSERT INTO table1(col1, col2, col3)
SELECT distinct col1, col2, getDate()
FROM table2 WHERE NOT EXISTS(
SELECT 1 FROM table1
WHERE ((table1.col1 = table2.col1) or (table1.col1 is null and table2.col1 is null))
AND ((table1.col2 = table2.col2) or (table1.col2 is null and table2.col2 is null)))
You can optimize this query quite a bit, but as a quick fix you could change:
SELECT 1 FROM table1, table2
to:
SELECT 1 FROM table1
This will tie the outer table2 into your subquery.

How to select distinct on specific columns

I have few columns in a table
Col1, Col2, Col3, Col4
Now I want to select like this
SELECT DISTINCT (Col1, Col2, Col3), Col4
i.e. get the distinct based on only these three colunms.
Just GROUP BY Col1, Col2, Col3 with an aggregate function with the col4 like MAX, MIN, etc .. like so:
SELECT Col1, Col2, Col3, MAX(Col4)
FROM TableName
GROUP BY Col1, Col2, Col3
From a comment to another answer:
Can I get like this Col1, Col2 , Col3 and (Col4 in delimiter form)
Yes, you can use the for xml path.
select Col1,
Col2,
Col3,
(
select ',' + T2.Col4
from YourTable T2
where T1.Col1 = T2.Col1 and
T1.Col2 = T2.Col2 and
T1.Col3 = T2.Col3
for xml path(''), type
).value('substring((./text())[1], 2)', 'varchar(max)') as Col4
from YourTable as T1
group by T1.Col1, T1.Col2, T1.Col3
SQL Fiddle
The group by and distinct perform almost similar functionality in SQL:
SO both queries below are almost equivalent:
SELECT DISTINCT Col1, Col2, Col3 FROM tbl
SELECT Col1, Col2, Col3 FROM tbl GROUP BY Col1, Col2, Col3
select distinct ( Convert(varchar(255),Col1) +' '+
Convert(varchar(255),Col2)+' '+Convert(varchar(255),Col3)),
Col4 from clients