I have a MySQL database called ice_cream with three tables, users, flavors, and favorites. Each record in favorites has a reference to a user and a flavor, and a user is able to have multiple ice cream flavors.
I'm trying to write a transaction to completely replace a user's favorites with another set of favorites. For example, when the API accepts
PUT /user/100/favorites
{
"flavors": {
"2": { "stars": 2 },
"3": { "stars": 5, "comments": "Changed my life" },
"18": { "stars": 4, "comments": "👅 " },
"24": { "stars": 4 }
}
}
The favorites table should change from
| id | user_id | flavor_id | stars | comments |
| --- | ------- | --------- | ----- | ------------------ |
| 200 | 100 | 2 | 2 | Tastes OK |
| 201 | 100 | 4 | 3 | |
| 202 | 100 | 5 | 3 | |
To
| id | user_id | flavor_id | stars | comments |
| --- | ------- | --------- | ----- | ------------------ |
| 200 | 100 | 2 | 2 | |
| 201 | 100 | 3 | 5 | Changed my life |
| 203 | 100 | 18 | 4 | 👅 |
| 204 | 100 | 24 | 4 | |
What's the most efficient set of statements to accomplish this?
Points to consider:
I'm not concerned with keeping primary ids consistent.
The users are really into the small-batch craft ice cream scene and will usually replace about 5000 records each transaction.
in this case the most efficient set of statements is delete and insert
delete from flavors
where user_id =100;
and a loop server side for insert the new values or a batch insert with all the values in repated values rows
insert into flavors ( user_id, flavor_id, stars , comments )
values ( 100,2 ,2 null),
(100, 3, 5 , 'Changed my life'),
(100 ,18,4 , 👅 ),
(100 , 24 ,4 , null)
Related
I have a table t with 2 fields: one containing an id, and the other one containing a json.
My table looks like this:
| id | json |
|:---|:----------------------------------------------|
| 1 | {"tag1":45, "tag2": 3, "tag5": 10} |
| 2 | {"tag5":35, "tag6": 7, "tag8": 10, "tag10": 4}|
| 3 | {"tag2":10, "tag800": 6} |
I am trying to write a postgresql query to create a table that looks like the following but I am stuck:
| id | key | Value |
|:---|:--------|:------|
| 1 | tag1 | 45 |
| 1 | tag2 | 3 |
| 1 | tag5 | 10 |
| 2 | tag5 | 35 |
| 2 | tag6 | 7 |
| 2 | tag8 | 10 |
| 2 | tag10 | 4 |
| 3 | tag2 | 10 |
| 3 | tag800 | 6 |
Note that there are thousands of different keys in my data.
Any help would be much appreciated. Thanks!
Recreating your example with
CREATE TABLE test(id int, mydata jsonb);
insert into test values (1, '{"tag1":45, "tag2": 3, "tag5": 10}');
insert into test values (2, '{"tag5":35, "tag6": 7, "tag8": 10, "tag10": 4}');
insert into test values (3, '{"tag2":10, "tag800": 6} ');
You can achieve what you're looking for with the jsonb_each function
select id, key, value from test, jsonb_each(test.mydata)
This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 2 years ago.
We have a situation where duplicate entries have crept into our table with more than 60 million entries (duplicate here implies that all fields, except the AUTO_INCREMENT index field have the same value). We suspect that there are about 2 million duplicate entries in the table. We would like to delete these duplicate entries such that the earliest instances of the duplicate entries are retained.
Let me explain with an illustrative table:
CREATE TABLE people
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(40) NOT NULL DEFAULT '',
age INT NOT NULL DEFAULT 0,
phrase VARCHAR(40) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
INSERT INTO people(name, age, phrase) VALUES ('John Doe', 25, 'qwert'), ('William Smith', 19, 'yuiop'),
('Peter Jones', 19, 'yuiop'), ('Ronnie Arbuckle', 32, 'asdfg'), ('Ronnie Arbuckle', 32, 'asdfg'),
('Mary Evans', 18, 'hjklp'), ('Mary Evans', 18, 'hjklpd'), ('John Doe', 25, 'qwert');
SELECT * FROM people;
+----+-----------------+-----+--------+
| id | name | age | phrase |
+----+-----------------+-----+--------+
| 1 | John Doe | 25 | qwert |
| 2 | William Smith | 19 | yuiop |
| 3 | Peter Jones | 19 | yuiop |
| 4 | Ronnie Arbuckle | 32 | asdfg |
| 5 | Ronnie Arbuckle | 32 | asdfg |
| 6 | Mary Evans | 18 | hjklp |
| 7 | Mary Evans | 18 | hjklpd |
| 8 | John Doe | 25 | qwert |
+----+-----------------+-----+--------+
We would like to remove duplicate entries so that we get the following output:
SELECT * FROM people;
+----+-----------------+-----+--------+
| id | name | age | phrase |
+----+-----------------+-----+--------+
| 1 | John Doe | 25 | qwert |
| 2 | William Smith | 19 | yuiop |
| 3 | Peter Jones | 19 | yuiop |
| 4 | Ronnie Arbuckle | 32 | asdfg |
| 6 | Mary Evans | 18 | hjklp |
| 7 | Mary Evans | 18 | hjklpd |
+----+-----------------+-----+--------+
On smaller sized tables the following approach would work:
CREATE TABLE people_uniq LIKE people;
INSERT INTO people_uniq SELECT * FROM people GROUP BY name, age, phrase;
DROP TABLE people;
RENAME TABLE people_uniq TO people;
SELECT * FROM people;
+----+-----------------+-----+--------+
| id | name | age | phrase |
+----+-----------------+-----+--------+
| 1 | John Doe | 25 | qwert |
| 2 | William Smith | 19 | yuiop |
| 3 | Peter Jones | 19 | yuiop |
| 4 | Ronnie Arbuckle | 32 | asdfg |
| 6 | Mary Evans | 18 | hjklp |
| 7 | Mary Evans | 18 | hjklpd |
+----+-----------------+-----+--------+
Kindly suggest a solution that would scale to a table with tens of millions of entries and many more columns. We are using MySQL version 5.6.49.
why not deleting duplicates?
DELETE FROM people
where id in (
SELECT MAX(id)
FROM people
GROUP BY name, age, phrase
HAVING count(*) > 1
)
if it still takes too much time , you can do it in batch
I'm trying to retrieve data from many to many relation grouped in one object for the duplicated date.
I have menu table and daily_mealz table and pivot table(menu_daily_mealz)
the problem is the daily_mealz contain duplicated date value in its date column but every raw contain different meal_id.
So, I need to retrieve one raw but contain all mealsIDs related to this date
I only retrieve with belongsTo relation and them for loop over the data to get the object I need.
Relations
public function dailyMeals(){
return $this->belongsToMany(DailyMeals::class, 'menu_daily_meals', 'menu_id', 'daily_meal_id');
}
public function menus(){
return $this->belongsToMany(Menu::class, 'menu_daily_meals', 'daily_meal_id', 'menu_id');
}
DataBase Structure
Menu table
+-----+----------------+
| id | name |
+-----+----------------+
| 1 | first menu |
| 2 | second menu |
+-----+----------------+
daily mealz table
+----+-------------+---------+-------+
| id | date | meal_id | stock |
+----+-------------+---------+-------+
| 1 | 2019-03-01 | 1 | 250 |
| | | | |
| 2 | 2019-03-01 | 2 | 100 |
| | | | |
| 3 | 2019-03-02 | 3 | 150 |
| | | | |
| 4 | 2019-03-02 | 4 | 70 |
| | | | |
| 5 | 2019-03-03 | 5 | 350 |
| | | | |
| 6 | 2019-03-03 | 6 | 180 |
+----+-------------+---------+-------+
Menu_daily_meals table
+----+---------+---------------+
| id | menu_id | daily_meal_id |
+----+---------+---------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 1 | 4 |
| 5 | 1 | 5 |
| 6 | 1 | 6 |
| 7 | 2 | 3 |
| 8 | 2 | 5 |
| 9 | 2 | 6 |
+----+---------+---------------+
I need to retrieve object like that
{
"id": 1,
"name": "first menu",
"daily_meals": [
{
"id": 1,
"daily_date": "2019-03-01",
"meals" : [
{
"meal_id" : 1,
"stock" : 250
},
{
"meal_id" : 2,
"stock" : 100
},
]
},
{
"id": 2,
"daily_date": "2019-03-02",
"meals" : [
{
"meal_id" : 3,
"stock" : 150
},
{
"meal_id" : 4,
"stock" : 70
},
]
},
{
"id": 3,
"daily_date": "2019-03-03",
"meals" : [
{
"meal_id" : 5,
"stock" : 350
},
{
"meal_id" : 6,
"stock" : 180
},
]
}
]
}
Any Help, Please?
You should use load function to load external data to your model(use eager loading):
$menu=Menu::find(1);
$menu->load('dailyMeals','dailyMeals.meals');
Note : For hide pivot object in response add this code to your menu model:
protected $hidden = ['pivot'];
Note : You should have dailyMeals in your menu model and meals relation in your dailyMeals model
For more information You can Visit Laravel Document.
Let's say I have a table fruit like this:
| text | id | time_end | parent_id |
| ------------|----|----------|-----------|
| banana tree | 23 | 200 | 7 |
| tomato vine | 84 | 500 | 7 |
| pear tree | 13 | 800 | 7 |
| apple tree | 40 | 1000 | 7 |
| grape vine | 15 | 1800 | 7 |
Now let's say I had a query that did a LIKE search. E.G.:
SELECT id, time_end FROM fruit WHERE text LIKE '%tree';
That would give me the data for banana tree, pear tree, and apple tree.
But suppose I wanted the data before each row, using the two-column index of time_end+parent_id. How do I do that with a minimum number of queries? In the example here, the output should be:
| text | id | time_end | time_start | parent_id |
|-------------|----|----------|------------|-----------|
| banana tree | 23 | 200 | 0 | 7 |
| pear tree | 13 | 800 | 500 | 7 |
| apple tree | 40 | 1000 | 800 | 7 |
You can do it like this :
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE fruit
(`text` varchar(11), `id` int, `time_end` int, `parent_id` int)
;
INSERT INTO fruit
(`text`, `id`, `time_end`, `parent_id`)
VALUES
('banana tree', 23, 200, 7),
('tomato vine', 84, 500, 7),
('pear tree', 13, 800, 7),
('apple tree', 40, 1000, 7),
('grape vine', 15, 1800, 7)
;
Query 1:
SELECT a.text,a.id, a.time_end,
IFNULL((select max(time_end) from fruit where time_end < a.time_end),0) as time_start,
a.parent_id
FROM fruit a WHERE a.text LIKE '%tree'
Results:
| text | id | time_end | time_start | parent_id |
|-------------|----|----------|------------|-----------|
| banana tree | 23 | 200 | 0 | 7 |
| pear tree | 13 | 800 | 500 | 7 |
| apple tree | 40 | 1000 | 800 | 7 |
For some reason I am having difficulty wording this question but I will try my best. I've been searching for 2 days on and off now and haven't found a good solution to the issue.
I have a Table called InventoryNode;
_________________________________________________
| InvID | ID | Slot | ItemID1 | ItemID2 | ItemID3 |
|-------|----|------|---------|---------|---------|
| 1 | 1 | Neck | 10 | 22 | 66 |
| 1 | 2 | Head | 26 | 23 | 56 |
| 1 | 3 | Leg | 19 | 21 | 76 |
And another table called Inventory which stores the Node ID in each column
_____________________________
| ID| Neck | Head | Leg | ... |
|---|------|------|-----|-----|
| 1 | 1 | 2 | 3 | 66 |
If there a way I can insert the node ID's into the Inventory table based off the InvID and populate all the columns with the correct name with the Node's ID?
Something like this?
INSERT INTO Inventory INNER JOIN InventoryNode ON
(Inventory.ID = InventoryNode.InvID) WHERE Inventory.column_name =
InventoryNode.Slot SET InventoryNode.InvID