MySQL SELECT Substring of rows that do not exist from other TABLE - mysql

I am sure this has been answered before, but I am just learning mysql and so I do not know how to properly search for the solution. I have two tables:
Table1 Table2
id email id domain
-- ---- -- ----
1 name#domain1.com 1 domain1.com
2 name#domain2.com 2 domain4.com
3 name#domain3.com
4 name#domain4.com
Using the emails in Table1, I would like to return the domains that do not exist in table2, and then write them to Table2, so I have a complete, unique list of domains in Table 2.
Table1 Table2
id email id domain
-- ---- -- ----
1 name#domain1.com 1 domain1.com
2 name#domain2.com 2 domain4.com
3 name#domain3.com 3 domain2.com
4 name#domain4.com 4 domain3.com

You can achieve this using a WHERE NOT IN with a sub query
INSERT INTO Table2 ( domain )
SELECT DISTINCT SUBSTRING_INDEX(email,'#',-1)
FROM Table1
WHERE SUBSTRING_INDEX(email,'#',-1) NOT IN (SELECT domain FROM Table2)

make the domain names a unique key in table2 then INSERT IGNORE select distinct substring() etc from table1
Alter table_2
add unique key k1(domain);
insert ignore into table_2(domain)
select distinct substring_index(email,'#',-1)
from table_1;
Where IGNORE will err ignore errors like duplicates.

Related

How to insert unique records from one table to another in MySQL

I've a sample table table1:
id transaction_number net_amount category type
1 100000 2000 A ZA
2 100001 4000 A ZA
3 100002 6000 B ZB
I've a sample table table2:
id transaction_number net_amount category type
1 100002 6000 B ZB
How do I insert unique records that are not in table2, but present in table1?
Desired result:
id transaction_number net_amount category type
1 100002 6000 B ZB
2 100000 2000 A ZA
3 100001 4000 A ZB
INSERT INTO table2 ( transaction_number, net_amount, category, type )
(
/* Rows in table1 that don't exist in table2: */
SELECT ( table1.transaction_number, table1.net_amount, table1.category, table1.type )
FROM table1
LEFT JOIN table2 ON ( table1.transaction_number = table2.transaction_number )
WHERE table2.transaction_number IS NULL
)
If you don't want to duplicate transaction numbers in table2, then create a unique index or constraint on that column (or the columns you want to be unique). Let the database handle the integrity of the data:
alter table table2 add constraint unq_table2_transaction_number
unique (transaction_number);
Then use on duplicate key update with a dummy update:
insert into table2 (transaction_number, net_amount, category, type)
select transaction_number, net_amount, category, type
from table1
on duplicate key update transaction_number = values(transaction_number);
Why do I recommend this approach? First, it is thread-safe, so it works even when multiple queries are modifying the database at the same time. Second, it puts the database in charge of data integrity, so the transactions will be unique regardless of how they are changed.
Note that the most recent versions of MySQL have deprecated this syntax in favor of the (standard) on conflict clause. The functionality is similar, but I don't think those versions are widespread.
Try this
INSERT INTO table2 (transaction_number,net_amount,category,type)
(SELECT transaction_number,net_amount,category,type from table1) ON DUPLICATE KEY UPDATE
net_amount=VALUES(net_amount),category=VALUES(category),type=VALUES(type);
Usw not exists as follows:
Insert into table2
Select t1.*
From table1 t1
Where not exists
(Select 1 from table2 t2
Where t1.transaction_number = t2.transaction_number)

insert into select on duplicate key update values(...) with MySQL

I have read that the function "values ()" is being removed in a future version - and I am therefore looking for an alternative - to if you have an "insert into select" command.
I have searched a lot on the web, but do not think I have found an answer - when it comes to "select" ...
Let's say I have 2 tables (t1 and t2) and some summations need to be written in t1 from t2.
t1:
product_id
quantity
total_value
1
3
100
2
2
80
t2:
product_id
value
1
50
1
50
1
50
2
40
2
50
Normally I would do it as follows:
insert into t1 (product_id,quantity,total_value)
select product_id,count(*),sum(value)
from t2 group by product_id on duplicate key update quantity=values(quantity),total_value=values(total_value)
This will give the following result:
t1:
product_id
quantity
total_value
1
3
150
2
2
90
But how do I do something similar if I can not use "values ()" ..?
It is of course an option to delete the relevant rows in t1 first - to avoid having a "duplicate key" at all - but is there no better way ..?
Thanks.
Normally I would do it as follows:
Use SELECT aliases:
insert into t1 (product_id, quantity, total_value)
select *
FROM ( SELECT product_id AS p, count(*) AS q, sum(value) AS s
from t2
group by p ) src
on duplicate key update quantity=q, total_value=s
But how do I do something similar if I can not use "values ()" ..?
The same
insert into t1 (product_id, quantity, total_value)
VALUES (1, 10, 100) AS x(p, q, s)
on duplicate key update quantity=q, total_value=s
fiddle

Update duplicate columns their foreign key - mysql

I have a table with products: a foreign key(fk id), name and more data. There are duplicates in name, but there are for example customers related to the fk id
Therefore I want to update the duplicates with the first matching fk id
Example:
fk id name
1 abc
2 abc
3 abc
67 abc
Table after update:
fk id name
1 abc
1 abc
1 abc
1 abc
So far I got a query to put them together in a comma separated list, but I am missing the Update:
SELECT
count(*) as amount,
group_concat(name) as names,
group_concat(id) as ids
FROM db.product
GROUP BY name
HAVING amount> 1;
In mysql you can use joins in update statements. I would create a subquery that returns the lowest id (min()) for each name that appears multiple times. Since in mysql you cannot select from the same table that is being updated, therefore an extra layer of subselect is added on the top of the subselect:
UPDATE db.product
INNER JOIN (SELECT * FROM
(SELECT name, min(id) as minid
FROM db.product
GROUP BY name
HAVING count(*)> 1) t2 ) t on t.name=db.product.name
SET db.product.id=t.minid;

Mysql - Merge multiple columns into one while preserving each value

Is there a simple way in Mysql to convert a multi-column resultset into a single-column resultset where each row in the single column contains a single value from each cell in the multi-column resultset?
For instance, say I have a table like:
id | fk1 | fk2 | fk3
1 2 3 4
5 6 7 8
Ideally I'd like to be able to run a query along the lines of:
SELECT <some_function>(fk1, fk2, fk3) AS value FROM myTable;
...and then get an output like:
value
2
3
4
6
7
8
Is there a straightforward way of doing so, or is the only real option to walk the multi-column resultset in code and extract the values into the format that I want?
The end goal is to be able to use the first query as a subquery in a context where the input can only be a single column of values, like:
SELECT * FROM myOtherTable WHERE id IN
(SELECT <some_function>(fk1, fk2, fk3) AS value FROM myTable);
Thus a pure SQL solution is preferable, if one exists.
The simplest way is to use union all:
select fk1 from mytable union all
select fk2 from mytable union all
select fk3 from mytable;
There are other methods, but this is simplest.
For your particular query, you can use exists and or or in:
SELECT mo.*
FROM myOtherTable mo
WHERE EXISTS (SELECT 1
FROM MyTable m
WHERE mo.id IN (m.fk1, m.fk2, m.fk3)
);
EDIT:
For performance, but an index on each fk column and use multiple conditions in the where:
SELECT mo.*
FROM myOtherTable mo
WHERE EXISTS (SELECT 1 FROM MyTable m WHERE mo.id = m.fk1) OR
EXISTS (SELECT 1 FROM MyTable m WHERE mo.id = m.fk2) OR
EXISTS (SELECT 1 FROM MyTable m WHERE mo.id = m.fk3);
This will do index lookups, which should be much faster than the original form.
Consider you table name tab1.
Now you can do query like
select fk1 from (
(select fk1 from tab1)
union all
(select fk2 from tab1)) as rt
group by fk1;
This will combine your two column in to one. Contains will appear one after another.

How to delete only duplicate rows?

How I can create an SQL command to delete all rows from table where I have two or more specific columns with the same value and still I don't lose that row, only the duplicates?
For example:
Id value1 value2
1 71 5
2 8 8
3 8 8
4 8 8
5 23 26
Id2, Id3 and Id4 have same value1 and value2.
I need to delete all duplicate rows like (Id3 and Id4) or (Id2 and Id4) or (Id2 and Id3)
delete t
from table1 t
inner join table1 t2
on t.id>t2.id and t.value1=t2.value1 and t.value2=t2.value2
Since MySQL allows ungrouped fields in queries:
CREATE TEMPORARY TABLE ids AS
(SELECT id
FROM your_table
GROUP BY value1, value2);
DELETE FROM your_table
WHERE id NOT IN (SELECT id FROM ids);
What you can do is copy the distinct records into a new table by:
select distinct * into NewTable from MyTable