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;
Related
I have 2 tables and i am joining them using the below Query
Select distinct EmailAddress,CUSTOMER_ID,Send_Date,Unique_key,sub_category
from table1
UNION ALL
Select distinct EmailAddress,CUSTOMER_ID,Send_Date,Unique_key,sub_category
from table2
I am using Unique_key as the primary key. It is the concatination of send date + customer id. Sometimes both the tables can have duplicate keys and hence I want to take only 1row in such cases using the above query
Table 1
EmailAddress CUSTOMER_ID Send_Date Unique_key sub_category
a#gmail.com 1001 07-08-2021 70820211001 chair
Table 2
EmailAddress CUSTOMER_ID Send_Date Unique_key sub_category
a#gmail.com 1001 07-08-2021 7082021100 book
What is expected results ?
EmailAddress CUSTOMER_ID Send_Date Unique_key sub_category
a#gmail.com 1001 07-08-2021 70820211001 chair
Only 1 record should appear in the final table & multiple rows should be skipped. I don't want to change anything in unique key format. Is there any workaround for this?
You need something like:
Select distinct EmailAddress,CUSTOMER_ID,Send_Date,sub_category
from table_1
UNION
SELECT EmailAddress,CUSTOMER_ID,Send_Date,sub_category FROM table_2
WHERE NOT EXISTS ( SELECT NULL
FROM table_1
WHERE table_1.EmailAddress = table_2.EmailAddress ) ;
The below select will return empty set, because you have the WHERE NOT EXISTS condition, return the non matching row.
SELECT EmailAddress,CUSTOMER_ID,Send_Date,sub_category
FROM table_2
WHERE NOT EXISTS ( SELECT NULL
FROM table_1
WHERE table_1.EmailAddress = table_2.EmailAddress
) ;
Demo: https://www.db-fiddle.com/f/pB6b5xrgPKCivFWcpQHsyE/24
Try with your data and let me know.
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.
id|number
12|c
21|e
31|a
43|a
43|a
43|b
52|x
52|x
52|x
53|d
In the above example, I want to keep all the rows corresponding to 43 and delete all belonging to 52.
We can try using aggregation logic here:
DELETE
FROM yourTable t1
WHERE
t1.id IN (SELECT id FROM (SELECT id FROM yourTable
GROUP BY id
HAVING COUNT(*) > 1 AND COUNT(DISTINCT number) = 1) x);
The restriction COUNT(*) > 1 ensures that the id has at least two records, while COUNT(DISTINCT number) = 1 ensures that this id has the same number value for all duplicates. We wrap the subquery once to avoid any possible MySQL errors about referring to a table while it is being deleted.
This should delete all rows corresponding to 52. Those with 43 and other ids will remain in the table.
DELETE FROM table_name WHERE id = 52;
There are basic operations; you will do well to read through some here.
Update: if you wish to delete only rows that correspond to duplicate id and number combination, you might try the below SQL. It uses the concatenation of id and the number to determine duplicates to remove.
DELETE FROM table_name WHERE id IN (
SELECT DISTINCT id from (
select concat(id,'-',number) as connum from table_name
group by connum
having connum > 1
)
)
I have two columns account_number and customer_id. A single customer can have multiple account but a single account can't have multiple customer.
I have dumped a file containing account_num and its corresponding customer_id to db through LOAD DATA INFILE command. Now I am trying to validate through query does any account which has come multiple times in a file has same customer_id or different customer_id in two different rows.
REQUIREMENT : i want to return those accounts which has come multiple times but having diferent customer ids
I tried with group by , but didn't get desired result.
This is my query which is not giving the desired result
SELECT ACCOUNT_NUM,UNIQUE_CUSTOMER_ID,COUNT(UNIQUE_CUSTOMER_ID)
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM, UNIQUE_CUSTOMER_ID
HAVING COUNT(ACCOUNT_NUM) > 1 AND COUNT(UNIQUE_CUSTOMER_ID) = 1;
Hope I am clear.
You can simply get the count of unique customer ids using COUNT(DISTINCT..) for every account_num and filter out those cases where count is more than 1, inside the HAVING clause:
SELECT
ACCOUNT_NUM,
COUNT(DISTINCT CUSTOMER_ID) AS unique_customer_count
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM
HAVING unique_customer_count > 1
Drop the customer check into a join query like so
DROP TABLE if exists t;
create table t(accountid int,cid int);
insert into t values
(1,1),(1,2).(1,1),(2,3),(3,4),(3,4);
select distinct t.accountid,t.cid
from t
join
(
select accountid,count(distinct cid) cids
from t
group by accountid having cids > 1
) s on s.accountid = t.accountid;
+-----------+------+
| accountid | cid |
+-----------+------+
| 1 | 1 |
| 1 | 2 |
+-----------+------+
2 rows in set (0.00 sec)
You can use EXISTS :
SELECT lf.*
FROM LINKAGE_FILE lf
WHERE EXISTS (SELECT 1 FROM LINKAGE_FILE lf1 WHERE lf1.ACCOUNT_NUM = lf.ACCOUNT_NUM AND lf1.UNIQUE_CUSTOMER_ID <> lf.UNIQUE_CUSTOMER_ID);
However, you can also aggregation with your query :
SELECT ACCOUNT_NUM, COUNT(DISTINCT UNIQUE_CUSTOMER_ID)
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM
HAVING COUNT(DISTINCT UNIQUE_CUSTOMER_ID) > 1;
By this, you can get only ACCOUNT_NUMs which have two or more CUSTOMER_IDs.
I have a table named 'Student' with columns 'Name' and 'Roll Number'
name Roll_Number
A 1
A 2
A 1
B 2
B 2
C 3
C 2
D 4
I want to delete all the rows from this table having same name but different Roll_number and insert those rows in new table 'Temp'. So after operation Both tables should be like this
Table Student
name Roll_Number
B 2
B 2
D 4
Table Temp
name Roll_Number
A 1
A 2
A 1
C 3
C 2
Because A and C, both have different values for Roll_Number column, So we delete all the entries of A and C from Student table and add it to Temp Table
So how this can be done through mysql query?
Try something like:
For Student table:
SELECT name, Roll_Number
FROM Student
GROUP BY name
HAVING COUNT(DISTINCT Roll_Number) = 1
For Temp table:
SELECT name, Roll_Number
FROM Student
GROUP BY name
HAVING COUNT(DISTINCT Roll_Number) > 1
Here is the query that work for me, created from SMA and Tim answers.
For inserting into Temp Table
INSERT INTO Temp (name, Roll_Number)
SELECT name, Roll_Number
FROM Student
WHERE name IN (SELECT name
FROM Student
GROUP BY name
HAVING COUNT(DISTINCT Roll_Number) > 1);
Deleting record query is same as mentioned by Tim
DELETE FROM Student
WHERE name IN (SELECT name FROM Temp)
Thanks to both of them
Here is a query to insert all records which, for a given name have more than one Roll_Number, into a new temporary table Temp:
INSERT INTO Temp (name, Roll_Number)
SELECT name, Roll_Number
FROM Student
WHERE name IN (SELECT name
FROM Student
GROUP BY name
HAVING COUNT(DISTINCT Roll_Number) > 1)
And here is a query to delete these same records from Student:
DELETE FROM Student
WHERE name IN (SELECT name FROM Temp)
Note that I did the insertion into the new table first before deleting them from the old table (for obvious reasons).