MySQL Insert or Update (Where 2 columns match) - mysql

I have a table structure like below (like dummy data below).
RecordId | UserId | TestId | Score
----------------------------------
1 | 1 | 4 | 98
2 | 1 | 5 | 92
3 | 1 | 6 | 91
4 | 2 | 4 | 99
5 | 2 | 5 | 07
6 | 2 | 6 | 08
I want to update the above but I don't have the RecordId handy.
So lets say UserId 2 on TestId 5 got a Score 55.
We don't currently know wether a record even exists for UserId 2 on TestId 5 so it needs to add the data if it doesn't already exist. If The UserId and TestId do already exist I need to update them.
I don't 'think' i want to use any of the replace queries as I have read that these delete the old record and a create new one, which would have a new Id.
I 'think' it needs to be update with a on duplicate update but i cannot get this to work?
Any help would be much appreciated.

Ok so here is the answer.
Turns out my query was fine but i needed to create a unique key
Here is the prepared SQL statement I used.
INSERT INTO test (UserId, TestId, Score) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE UserId=? TestId=? Score=?;
To make this update when unique combination of UserId & TestId I used the follow SQL query.
ALTER TABLE test ADD UNIQUE KEY `UserTests` (`UserId`, `TestId`);
I hope this & my explanation helps someone out.

Related

Use ON DUPLICATE KEY UPDATE to update row with MySQL

I've the following table structure:
Table ___Availabilities :
|--------|------------|------------|------------|
| AVA_Id | AVA_RoomId | AVA_Date | AVA_Status |
|--------|------------|------------|------------|
| 1 | 47 | 2019-03-11 | NoData |
| 2 | 48 | 2019-03-22 | Book |
| 3 | 48 | 2019-03-23 | Book |
|--------|------------|------------|------------|
I want to UPDATE the AVA_Status only if AVA_RoomId and AVA_Date are know in a row of the table. If not, INSERT a new row.
So my query is this one:
INSERT INTO ___Availabilities
(AVA_Id, AVA_RoomId, AVA_Date, AVA_Status)
VALUES('', '103', '2019-04-04', 'Open')
ON DUPLICATE KEY UPDATE
`AVA_RoomId`='47',
`AVA_Date`='2019-03-11'
But it doesn't work as it added a new row whereas it should update the row where AVA_RoomId = 47 and AVA_Date = 2019-03-11.
Why my query is not working please ?
Thanks.
Assuming there is a UNIQUE INDEX(AVA_RoomId, AVA_Date)
You might want to update the AVA_Status when the combination of room and date already exists:
INSERT INTO ___Availabilities
(`AVA_RoomId`, `AVA_Date`, `AVA_Status`)
VALUES('103', '2019-04-04', 'Open')
ON DUPLICATE KEY UPDATE
`AVA_Status` = VALUES(`AVA_Status`),
As #Barmar already explained, if not already done, you can still add an index after table creation:
ALTER TABLE `___Availabilities`
ADD UNIQUE INDEX `uq_room_date` (`AVA_RoomId`, `AVA_Date`)
;

Unique value combination in MySQL

I'm building a simple friendship table with 3 columns: id, user1, user2
Once a user becomes friends with another user, their ids will be added to the table like this:
+----+-------+-------+
| id | user1 | user2 |
+----+-------+-------+
| 1 | 15 | 9 |
+----+-------+-------+
| 2 | 9 | 32 |
+----+-------+-------+
The above table is ok but in some cases, a user might want to become friends with a user they are already friends with, resulting in the following table:
+----+-------+-------+
| id | user1 | user2 |
+----+-------+-------+
| 1 | 15 | 9 |
+----+-------+-------+
| 2 | 9 | 32 |
+----+-------+-------+
| 3 | 9 | 15 |
+----+-------+-------+
In this table, index 1 and 3 are in conflict with each other (2 & 3 are NOT) and I would therefore like an error returned upon insertion (duplicate entry). Is there a way to do this?
When inserting into this table, before you issue the query, you should always make sure that user1 has the smaller of the two user IDs. Then the situation you described will never happen.
You can implement this either in your application code, or as a stored procedure that you execute to insert a new relation between two users.
Let me offer another perspective. You might want to keep the friends table as a reciprocal relationship. So, both directions would be stored in the table. The correct table would look like:
----+-------+-------+
| id | user1 | user2 |
+----+-------+-------+
| 1 | 15 | 9 |
+----+-------+-------+
| 2 | 9 | 15 |
+----+-------+-------+
| 3 | 9 | 32 |
+----+-------+-------+
| 4 | 32 | 9 |
+----+-------+-------+
Why would you want to do just an absurd thing, doubling the size of the data? Typical queries on such data are about who is a friend of friend or to list all the friends of a given user. Such queries require traversing this data as a graph structure, and you need both links. Not only do such queries become much more complicated with a single row per friendship, but because subqueries (derived tables) are often involved, the query loses the ability to use indexes.
With this structure, you need to be careful when inserting to insert both directions of the relationship. Then a simple unique constraint on the two columns ensures that duplicates are not inserted.
You can create a trigger to automatically fix this, similar to Dmytro's answer:
CREATE TRIGGER trgr_uid_check BEFORE INSERT ON Relationships
FOR EACH ROW
BEGIN
IF NEW.user1 > NEW.user2 THEN
SET #user1 = NEW.user1;
SET NEW.user1 = NEW.user2;
SET NEW.user2 = #user1;
END IF;
END
You could do a simple query to check if there is already a friendship:
SELECT id
FROM your_table
WHERE (user1 = numToInsert1 AND user2 = numToInsert2)
OR (user1 = numToInsert2 AND user2 = numToInsert1)
If this statement returns anything it means that there is already a friendship between those two. If this statement does not return anything insert your new friendship.

SQL query to remove multiple duplicate entries from table

I have table containing following entries
Id | Accno | Name | Hash
----+----------+-----------+---------
1 | 11 | ABC | 01110
2 | 11 | ABC |
3 | 22 | PQT |
4 | 33 | XYZ | 03330
5 | 44 | LMN | 04440
6 | 33 | XYZ |
I need SQL query to remove duplicate entry from table and keep atleast single entry in table whose hash value is present. and for those entries which are not duplicate should also remain in table.
I think you guys overcomplicate things a lot. This should work just dandy:
DELETE FROM
YourTable
WHERE Hash IS NULL
AND Accno IN
(
SELECT Accno
FROM YourTable
GROUP BY Accno
HAVING COUNT(Name) > 1
)
;
Probably the easiest way to do it is to create a new table and copy non duplicate entries.
create table table_name2 as select distinct * from table_name1;
drop table table_name1;
rename table_name2 to table_name1;
Something like this.
Create table temp2 as SELECT *
FROM temp where id in (select id from temp group by accno having count(accno)>=1 and hash<>'');
drop table old_table;
rename table temp2 to old_table;
Check SQL Fiddle

MYSQL delete duplicate record in same group and keep only one [duplicate]

This question already has answers here:
How do I delete records in MySQL and keep the lastest date
(3 answers)
How do I delete all the duplicate records in a MySQL table without temp tables
(9 answers)
How do I remove duplicates rows in my MySQL database? (Keep the one with lowest Primary ID)
(4 answers)
Closed 9 years ago.
I searched but all of the questions come up with delete duplicate record and keep only one latest in table, but my is a bit difference, I want to delete duplicate record in the same group but keep only latest record of that group. Here is an example:
ID Device_ID Time Content Text
1 abc 2013-11-30 15-30-01 I love you
2 abc 2013-11-30 15-30-01 I love you
3 def 2013-10-30 12-12-02 I love you
4 def 2013-10-30 12-12-02 I love you
5 ghj 2013-09-30 11-12-02 I love you
6 ghj 2013-09-30 11-12-02 I love you
So there are some devices having same content with other device, I would like find a way to delete duplicate content in each device id and delete duplicate and keep the latest.
If I select group by content text then delete it from there then it would delete all others content from other device as well and I can't do that.
Assume I have 50 million records. So is there a way I can delete duplicate record on each device id the result would be like only having I love you content text on each device id.
I can't make my column content text as unique during inert because there might be some device id using same content text. Or maybe unique time but then each device id might insert same time but difference content text...
I would like res
ID Device_ID TimeContent Text
2 abc 2013-11-30 15-30-01 I love you
4 def 2013-10-30 12-12-02 I love you
6 ghj 2013-09-30 11-12-02 I love you
Try:
DELETE FROM tblA
WHERE id NOT IN (
SELECT DISTINCT id FROM (
SELECT MAX(id) as id FROM tblA
GROUP BY Device_ID, Time, ContentText
HAVING COUNT(*) > 1 ) A
);
See Demo
Try this:
DELETE FROM TableA
WHERE id NOT IN (SELECT id
FROM(SELECT MAX(id) id FROM TableA t
GROUP BY t.Device_ID, t.Time, t.ContentText HAVING COUNT(*) > 1
) AS A
);
Check the SQL FIDDLE DEMO
OUTPUT
| ID | DEVICE_ID | TIME | CONTENTTEXT |
|----|-----------|---------------------|-------------|
| 2 | abc | 2013-11-30 15-30-01 | I love you |
| 4 | def | 2013-10-30 12-12-02 | I love you |
| 6 | ghj | 2013-09-30 11-12-02 | I love you |
| 13 | ghj1 | 2013-09-30 11-12-02 | I love you |
NVM i found the problem just switch Count * > 1 to 0 , it will not delete the non duplicate

How to query the look up table for unique values?

I have a recipe table that is structured like this:
product2recipe
id | productid | recipeid
I want to eliminate insertion of duplicate values. Basically a recipe can contain 1 or more productid. So it looks like this:
1 | 1 | 1
2 | 2 | 1
3 | 1 | 2
4 | 5 | 3
The user can submit a new recipe, if the recipe contains similar value like:
id | 1 | 4
id | 2 | 4
Then it should not submit, because the table already have duplicate values, recipeid 1 contains productid 1 and 2 already. If it is:
id | 1 | 5
id | 3 | 5
Then it should submit since this is a unique combination.
How can I query my table optimally? I'm afraid that it might stall my database server since there's possibly many combinations.
The example you have provided does exactly tells us what you want because those records does not exist on the table.
But anyway, here's a way to enforce a UNIQUE constraint for compound column in your table,
ALTER TABLE product2recipe ADD CONSTRAINT tb_uq UNIQUE(productid, recipeid)
SQLFiddle Demo
uncomment the ALTER TABLE statement in the demontration link above and see what happens
Given a known set of products for a "new" recipe, I would suggest running the following query:
select recipeid
from product2recipe
group by recipeid
having count(distinct productid) =
count(distinct case when productid in (?,?,...) then productid end)
- any recipes returned will have the same set of products as the "new" recipe; your application should then be programmed to reject such "new" recipes.