I've been trying to figure out how to get my query to update an existing row if 2 values match
I have a table with this data
id | itemid | date | price
____________________________________________________________________________
eef1879a-4506-437c-801a-b874e38e290d | 123 | 2015-04-26 08:42:32 | 3.42
67391c5e-09ab-4c2f-b80e-fb0ce69f6e5d | 123 | 2015-04-27 20:02:32 | 3.50
6b16fba4-389e-40ae-94f8-7917ab09fd39 | 13512 | 2015-04-26 08:13:32 | 1.54
5ec3dfe0-29bf-48c8-a694-89606cdbfba3 | 13512 | 2015-04-27 20:02:32 | 1.70
808dc4a3-daa0-4470-b08a-4650f7f4d8e9 | 2124 | 2015-04-26 08:42:28 | 8.74
e327aa9e-fe02-4ccb-8543-752fe5d86e2c | 2124 | 2015-04-27 20:02:32 | 9.04
de4d69ce-eca0-419f-8514-1cc0509149dd | 2124 | 2015-04-28 17:04:02 | 9.78
f7efdcf3-9dd1-41ee-880b-b18563d6f934 | 13512 | 2015-04-28 13:07:30 | 2.09
c256fed7-8a09-4afe-97f3-0e5a9ceea930 | 123 | 2015-04-28 02:08:38 | 3.52
I have an insert query that's working fine. But I don't want multiple entries per day. I've seen ON DUPLICATE KEY for a single column unique key, but my PK is a uuid v4 that's generated via PHP on the insert.
I'm currently checking in a SQL query if the value exists, if it doesn't to insert it. However this is creating an issue if the process gets kicked off more than once. I'm trying to failsafe not having duplicate prices per day.
Current SQL to check if exists:
$date = DATE('Y-m-d');
SELECT i.id FROM items as i
LEFT JOIN itemprices as ip
ON i.id=ip.itemid
AND date(ip.date) = \"$date\"
WHERE ip.itemid IS NULL
It checks the list of item's to see what it needs to create a price for that day. The array that comes back from this is valid at this point.
Then I just do an insert per item with the appropriate value that I get from my endpoint.
Currently my data set that I'm getting prices for each day is 14000 lines, so processing things more than once is extra stress on MySQL and requires manual cleanup.
... ON DUPLICATE KEY ..
Also applies for composite unique/primary keys. Simply rebuild your PK as a composite index.
Related
I have message table in dynamodb with the following fields:
Primary partition key => conversation_id
Primary sort key => id
other attributes => message,date_time,sender_id
+------------------+----------+----------------------+------------------------+----------+
| conversation_id | id | message | date_time | sender_id|
+----------------------------------------------------+------------------------+----------+
| p1OS9E | S04Ln | Hi.. how are you..? | 2016-11-30 06:58:11 pm | 11 |
| p1OS9E | JZkSo | Work finished..? | 2016-11-30 06:58:13 pm | 11 |
| p1OS9E | EN9N4 | I am fine. | 2016-11-30 06:58:12 pm | 12 |
| | | | | |
| a0zgOO | jmDdm | In online..? | 2016-12-40 08:43:12 pm | 51 |
| a0zgOO | mAEdY | Yes.. say.. | 2016-12-40 08:43:14 pm | 34 |
| a0zgOO | aWKrp | Come to play.. | 2016-12-40 08:43:12 pm | 51 |
+------------------+----------+----------------------+------------------------+----------+
While query items based on partition key, the result returned as unordered(not in inserted order).
The sort key id, AttributeType is `string', a random generated code to make the Primary key as unique.
First i used date_time as sort key, but if within same conversation_id with same date_time a message will enter. So the data loss may occur.
How to get my items with the order the message get inserted(based on time)..?
Note: I am using PHP (Codeigniter MVC).
There are many ways you can achieve this, the following are the two approaches that I generally use:
1) Add indexes: You need to add LSI(local secondary index) to your table with range key as DateTime.
Now you can query you LSI by passing you hash key and for DateTime you can use >= or >= operators to get in sorted order.
2) Sorting at application level: I personally use this solution as we don't have to pay additional amount for index, Get all data based on Hash then sort manually at application level by DateTime
There is one more answer of mine with a similar issue.
Hope that helps
I have the following Mysql-table:
+-------+--------+------------+----+-------+
| Name | Number | Department | id | JobID |
+-------+--------+------------+----+-------+
| Sven | 2204 | Marketing | 10 | 111 |
| Peter | 2304 | IT | 20 | 222 |
| Bjorn | 4409 | IT | 30 | 333 |
+-------+--------+------------+----+-------+
I get the three columns: Name, Number, Department from a system where I don't have the id and need to perform something in my php script.
Now I would like to performa an insert if there is a new record. If there is an existing record I would like to perform an update, if something changed like Name, Number or Department.
For example, if Number changes it should compare Name and Department and then change number. If Departmend changes it should compare Name and Number and then change Department and so on.
The problem is, that I can not use insert...on duplicate key, because I don't get the primary key.
If I use Replace Into it deletes me also the entry for JobID. Is there a solution how to perform a sql that it will insert and also update if there is now entry? Or something that can do the trick?
Thanks for your help!
I wanted to create a system to track the progress of a player in a game. Each player can be a member of multiple groups, which all have other requirements. In order to track his progress, the stats of the player will be saved once he joins a group. Every time he reloads his stats, the current ones should be saved inside the database.
All stats of the player are stored in a json-format, which will then be parsed either by PHP or JS. An entry with compare = 0 is set once the player joins a group. An entry with compare = 1 should be created the first time a player clicks on Update Stats and from then on it should only be updated, not newly created.
Now my question is: How to achieve that? When reading through the syntax of INSERT INTO I got the following:
INSERT INTO `groups` (`grp`, `id`, `json`, `compare`) VALUES
($grp, $id, $json, 1) ON DUPLICATE KEY SET `json` = $json
However, since there is no key set, and I don't know if I can set up two/three keys (as there can be multiple groups per user, as well as the compare = 0 entry in the same group), I don't think I can do it this way.
+------+----+---------+---------+
| grp | id | json | compare |
+------+----+---------+---------+
| 1 | 1 | stats | 0 |
| 1 | 1 | stats | 1 |
| 1 | 2 | stats | 0 |
| 1 | 2 | stats | 1 |
| 2 | 2 | stats | 0 |
| 2 | 3 | stats | 0 |
| 2 | 3 | stats | 1 |
| 2 | 4 | stats | 0 |
| 2 | 5 | stats | 0 |
+------+----+---------+---------+
grp is the group of the player. There is no real limit set to the
number of groups a player can be in.
id is the ID of the player.
json contains the stats of the player in a json
format (number of points, etc).
compare is a boolean. 0 stands for entry stats (the number of points a player
already had when he registered) and 1 stands for the current stats - Which will
be compared to the entry stats, in order to get the difference (= the points a
player made since joining the group).
I hope my explanation was understandable and someone can help me out.
You can use insert raplace:
REPLACE INTO groups (`grp`, `id`, `json`, `compare`) VALUES (...);
But you must have primary key in table. Replace into automaticly finds out primary key and if record exists, it update row, but if doesn't, it add new row.
You can create a unique key with multiple columns. This will trigger the 'on duplicate' clause.
ALTER TABLE groups
ADD UNIQUE (grp, id, compare)
I'm displaying a record set using Datatables pulling records from two tables.
Table A
sno | item_id | start_date | end_date | created_on |
===========================================================
10523563 | 2 | 2013-10-24 | 2013-10-27 | 2013-01-22 |
10535677 | 25 | 2013-11-18 | 2013-11-29 | 2013-01-22 |
10587723 | 11 | 2013-05-04 | 2013-05-24 | 2013-01-22 |
10598734 | 5 | 2013-06-14 | 2013-06-22 | 2013-01-22 |
Table B
id | item_name |
=====================================
2 | Timesheet testing |
25 | Vigour |
11 | Fabwash |
5 | Cruise |
Now since the number of records returned is going to turn into a big number in near future, I want the processing to be done serverside. I've successfully managed to achieve that but it came at a cost. I'm running into a problem while dealing with filters.
From the figure above, (1) is the column whose value will be in int (item_id), but using some small modifications inside the while loop of the mysql resource, I'm displaying the corresponding string using Table B.
Now if I use the filter (2), it is working fine since those values come from Table A
The Problem
When I try to filter from the field (3), if I enter a string value such as fab it says no record found. But if I enter an int such as 11 I get a single row which contains Fabwash as the item name.
So while filtering I'm required to use the direct value used in Table A and not its corresponding string value stored in Table B. I hope the point that I'm putting across is understandable because it is hard to explain it in words.
I'm clueless on how to solve the issue.
I want to insert into the cart table
**orderId** | cartId | cartDate | cartStatus
____________________________________________
1 | 1 | 20120102 | complete
2 | 2 | 20120102 | complete
3 | 3 | 20120102 | complete
4 | 4 | 20120102 | complete
using the auto increment value orderId from the order table
**orderId** | orderStatus | secret | sauce
____________________________________________
1 | 7 | 020200202 | bbq
2 | 6 | 020200202 | bbq
3 | 6 | 020200202 | t
4 | 4 | 020200202 | m
INSERT INTO ordertable VALUES(null,7,020200202,bbq)
but then using the orderId (which will now be 5)
INSERT INTO carttable VALUES(orderId,20120102,complete)
However,
this insert must be done as the same query. If I use mysql_last_id (php) there is an opportunity for someone else to insert into the database before my cart insert is executed. Or the connection might timeout. The database is MyISAM (and I can not change this, 3rd party solution).
Thank you,
J
I think your concern about using mysql_last_id is unfounded - it will return the last id for the current connection, not the last id globally across all connections.
So unless you have multiple threads sharing the same database connection or you perform another identity insert on the same connection before calling mysql_last_id, you should have nothing to worry about.
ETA: You could do this by sending multiple queries at once, like this:
INSERT INTO ordertable VALUES(null,7,020200202,bbq);
INSERT INTO carttable VALUES(LAST_INSERT_ID(),20120102,complete);
But if you are using mysql_query it usually won't let you send multiple queries in the same call (mostly as a security measure to try to prevent SQL injection).