Conditionally move MySQL data between rows in same table - mysql

Working in Redmine, I need to copy(not move) data from certain rows to other rows based on matching project id numbers with time entries.
I have included a diagram of the table "custom_values" and my understanding of the design below(CURRENT DATA):
+----+-----------------+---------------+-----------------+-------+
| id | customized_type | customized_id | custom_field_id | value |
+----+-----------------+---------------+-----------------+-------+
| 1 | Project | 1 | 1 | 01 |
| 2 | TimeEntry | 1 | 4 | 01 |
| 3 | Project | 2 | 1 | 02 |
| 4 | TimeEntry | 2 | 4 | 02 |
| 5 | Project | 3 | 1 | 03 |
| 6 | TimeEntry | 3 | 4 | |
| 7 | Project | 4 | 1 | 04 |
| 8 | TimeEntry | 4 | 4 | |
+----+-----------------+---------------+-----------------+-------+
At the risk of oversimplifying,
"id" = The primary key for each entry in custom_values
"customized_type" = Specifies which db table the row is referring to.
"customized_id" = Specifies the primary key for the db table entry previously specified in "customized_type".
"custom_field_id" = Specifies which custom field the row is referring to. Redmine admins can arbitrarily add and remove custom fields.
"value" = The data contained within the custom field specified by
"custom_field_id"
In my situation, the values listed in "value" are representing unique customer id numbers. The customer id numbers did not always get entered with each time entry. I need to copy the customer numbers from the project rows to the matching time entry rows. Each time entry has a project_id field.
So far, here is my mangled SQL query:
SELECT
custom_field_id,
custom_values.value AS 'CUSTOMER_NUMBER',
custom_values.customized_id AS 'PROJECT_ID_NUMBER',
custom_values.customized_type,
time_entries.comments AS 'TIME_ENTRY_COMMENTS'
FROM
redmine_tweaking.custom_values
LEFT JOIN
redmine_tweaking.time_entries ON custom_values.customized_id = time_entries.project_id
WHERE
custom_values.customized_type='Project' AND custom_values.custom_field_id=1;
The query I have so far allows me to see that I have the time entries connected properly to their matching projects, but that is all I have been able to figure out. So in other words, this SQL statement does not exactly solve my problem.
Plus, even if it did work, I think the way I laid it out looks like 200 lbs of bird poop. There must be a better/more optimized way to do this.
Any help would be greatly appreciated. I am relatively new and I have been pouring hours into solving this problem.
UPDATE:
Ok, here is the time_entries table:
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
| id | project_id | user_id | issue_id | hours | comments | activity_id | spent_on | tyear | tmonth | tweek | created_on | updated_on |
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
| 1 | 1 | 1 | 1 | .25 | test | 9 | 2015-11-04 | 2015 | 11 | 45 | 2015-11-04 08:18:12 | 2015-11-04 10:18:12 |
| 2 | 2 | 1 | 1 | .25 | test2 | 9 | 2015-11-04 | 2015 | 11 | 45 | 2015-11-04 09:18:12 | 2015-11-04 12:18:12 |
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
As opposed to the original table that I first posted, the expected output would show this:
+----+-----------------+---------------+-----------------+-------+
| id | customized_type | customized_id | custom_field_id | value |
+----+-----------------+---------------+-----------------+-------+
| 1 | Project | 1 | 1 | 01 |
| 2 | TimeEntry | 1 | 4 | 01 |
| 3 | Project | 2 | 1 | 02 |
| 4 | TimeEntry | 2 | 4 | 02 |
| 5 | Project | 3 | 1 | 03 |
| 6 | TimeEntry | 3 | 4 | 03 |
| 7 | Project | 4 | 1 | 04 |
| 8 | TimeEntry | 4 | 4 | 04 |
+----+-----------------+---------------+-----------------+-------+

Related

MySQL - Is there a better way to structure one of my table to reduce the amount of columns?

I have a (3x3) table on my website which gives the users the option to unlock a car slot, purchase a car and upgrade the car level.
In total I end up with 9 slots, all 9 slots can have different values (car_unlocked (bool), car_level (int), car_type (int)).
my current table : (user_cars)
id (AUTO_INCR) | user_id | car_slot_unlocked01 | car_level01 | car_type01 | car_slot_unlocked02 | car_level02 | car_type02 | car_slot_unlocked03 | car_level03 | car_type03 | car_slot_unlocked04 | car_level04 | car_type04 …
And so on until 9. I end up with 29 columns. And then I retrieve the values with the user_id on my website. Values are unique to every user.
How would I go about reducing the columns amount, because if I was to add more rows (4x4) or (5x5) to my website table I would end up with alot more columns in my database.
Do I create different db table and join it if that is even an option?
Thank you in advance.
Maybe you can give an ID to the cars so you don't need the repeating columns... something like:
id | user_id | car_id | car_slow_unlocked | car_level | car_type
-----------------------------------------------------------------
1 | 001 | 01 | 1 | 3 | 3
2 | 001 | 02 | 0 | 5 | 2
3 | 001 | 03 | 0 | 5 | 3
4 | 001 | 04 | 1 | 6 | 1
5 | 001 | 05 | 1 | 1 | 1
6 | 001 | 06 | 0 | 5 | 2
7 | 001 | 07 | 0 | 5 | 3
8 | 001 | 08 | 1 | 6 | 1
9 | 001 | 09 | 1 | 1 | 1
10 | 002 | 01 | 1 | 5 | 3
11 | 002 | 02 | 0 | 3 | 1
12 | 002 | 03 | 1 | 1 | 1
... and so on
Seems like you need to have a think about your data model. I don't quite understand your business but start with identifying the entities and their attributes outside of any presentation concerns.
e.g.
CarInstance (ID, type, unlocked)
CarType(ID, CarID, Level)
User(ID, name)
UserToCar(userID,carID)
I doubt those are right but that's the kind of thing you need to be aiming for. You can then generate your table from that.

Storing changes on MySQL Database properly

I've currently got three tables to track changes on specific entries but it seems like I am ending up with a ton of entries and I am not sure if that is the best possible way.
My first table holds the basic information and the second and third one the extra entries I grab every 8 hours.
ID | creation_date | removal_date | article_url | status which are basically the most stable entries. Status and removal_date are the only ones that will change in case we disable/remove an entry.
Example:
ID | creation_date | removal_date | article_url | status
---|------------------|------------------|-------------|-------
1 | 10/01/2020 20:00 | NULL | http://xxx | 1
2 | 23/01/2020 10:00 | 27/01/2020 13:00 | http://xxx2 | 2
3 | 10/02/2020 15:00 | NULL | http://xxx3 | 1
Status 1 = Active
Status 2 = Inactive
The second table holds everything else:
ID | main_id | last_update | title | description | views | rating | comments
The second table creates a new entry every 8 hours as long as something changes. Then based on the entries added here, I show average views/rating/comments changes on a daily/weekly/monthly basis.
Example:
ID | main_id | last_update | title | description | views | rating | comments
---|---------|------------------|----------------|--------------------|-------|--------|---------
1 | 1 | 10/01/2020 20:00 | First Article | Description.. | 1 | 1 | 0
2 | 2 | 23/01/2020 10:00 | Second Article | Desc.. | 1 | 1 | 0
3 | 1 | 11/01/2020 20:00 | First Article | Description update | 15 | 3 | 2
4 | 1 | 12/01/2020 20:00 | 1st Article | Description update | 30 | 5 | 4
5 | 3 | 10/02/2020 15:00 | 3rd Article | Descript! | 3 | 1 | 1
The third table holds the tags:
ID | main_id | tag_id | date_added | date_removed
I thought instead of having a status to add an empty date_removed so in case the tags get updated/removed/etc update that part. The tags are saved in a separate table and just grab the id and store the connection between the two here.
Example:
ID | main_id | tag_id | date_added | date_removed
---|---------|--------|------------------|------------------
1 | 1 | 2 | 10/01/2020 20:00 | NULL
2 | 1 | 3 | 15/01/2020 16:30 | 17/01/2020 13:00
3 | 2 | 3 | 23/01/2020 10:00 | NULL
4 | 3 | 5 | 10/02/2020 15:00 | NULL
5 | 1 | 5 | 11/02/2020 17:00 | NULL
I'd just like to know if there is a better / more proper way to store the above data.
Yepp, #Maria, is clearer.
Assuming that you are dealing with blog entries, you may have a data model like this.
Table 1. articles. // where every article is created.
article_id | article_creation_date | article_title | article_url | article_creator_id | article_description |
-----------|-----------------------|---------------|-------------|--------------------|------------------------------|
1 | 2020/03-31 10:36:05 | "The Dilemma" | /articles/1 | 23 | Explains the relations....|
Table 2. article_status // stores changes of state to each article.
article_status | article_id | status | date_of_change |
---------------|------------|--------|--------------------|
1 | 1 | 7 | 15/04/2020 09:30:00|
Table 3. article_tags. // every article and it's tags
article_tag | article_id | tag_id | date_added |
------------|------------|--------|--------------------|
1 | 1 | 24 | 15/04/2020 09:30:00|
Table 4. article views // stores the summarized amount of views to each article, for a period, say day, week, 8 hours,...
article_v_id | article_id | views_summarized | time_lapse | time_lapse_value | date_summarization |
-------------|------------|------------------|----------------|-------------------|-------------------|
1 | 1 | 1578 | Day | 10/04/2020 | 12/04/2020 13:27:04 |
Table 5. article_updates // stores changes/updates made to each article.
article_update_id | article_id | type_of_update | update_detail | update_author | date_of_update |
------------------|------------|--------------------------------|---------------|------------------------|
1 | 1 | Title | | John Doe | 19/04/2020 15:27:24 |
And the contentn of the update is stored directly on articles table, say change of title. NO need to store all modified titles, content. Just the event and who made the change.

How to bring columns to a table from another table by the Id?

I have this tables People, Ticket, and Report.
+----------+-------+-----+
| idPeople | Name | Age |
+----------+-------+-----+
| 1 | Name1 | 21 |
| 2 | Name2 | 37 |
| 3 | Name3 | 28 |
+----------+-------+-----+
I would like to replace the ForeingKey idPeople with columns Name and Age from People table.
+----------+------------+------------+----------+
| idTicket | ticketCol2 | ticketCol3 | idPeople |
+----------+------------+------------+----------+
| 5 | True | 01/06/99 | 1 |
| 6 | False | 01/06/99 | 2 |
| 7 | True | 01/06/99 | 4 |
+----------+------------+------------+----------+
In the Report table replace the Foreing Key idTicket with ticketCol2, Name, Age from the previous table Ticket with replaced columns (idPeople by Name, Age).
+----------+----------+------------+------------+
| idReport | idTicket | ReportCol3 | ReportCol4 |
+----------+----------+------------+------------+
| 1 | 5 | 01/06/99 | blabla |
| 2 | 7 | 01/06/99 | asdfdd |
| 2 | 6 | 01/06/99 | fooboo |
+----------+----------+------------+------------+
And I the result should be like this table and must be done in one query.
+----------+------------+------------+------------+------------+------+-----+
| idReport | ticketCol2 | ticketCol3 | ReportCol3 | ReportCol4 | Name | Age |
+----------+------------+------------+------------+------------+------+-----+
| 1 | 01/06/99 | abcd | blabla | 123456 | Name | 20 |
| 2 | 01/06/99 | bcda | asdfdd | 321456 | Name | 23 |
| 3 | 01/06/99 | asdf | fooboo | 123456 | Name | 28 |
+----------+------------+------------+------------+------------+------+-----+
I Have tried replacing the foreingkeys with LEFT JOIN and bringing some columns Name and Age to the Ticket table but now the last part where I should replace idTicket with Columns from Ticket is not working.
I have read about the nested JOINs but I cannot understand it very well, I would really appreciate some idea of how I can do it or what should I investigate. Are nested Joins the right way?
The query that I've tried to accomplish the Table Ticket.
SELECT Ticket.ticketCol2, Ticket.ticketCol3, p.Name 'Name', p.Age 'Age'
from Ticket
left join people p on (Ticket.idPeople=p.idPeople);
Try something like this:
SELECT Report.idReport,
Ticket.ticketCol2,
Ticket.ticketCol3,
Report.ReportCol3,
Report.ReportCol4,
People.Name,
People.Age
FROM People
LEFT JOIN Ticket ON Ticket.idPeople = People.idPeople
LEFT JOIN Report ON Report.idTicket = Ticket.idTicket
Like #RiggsFolly said, the Ticket.idPeople won´t match to the People.idPeople, so this will not match any rows.

MYSQL Insert into table's column based on column name

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

how to insert average of a query into mysql table

I am trying to get average of latency for each items that holds into two separate mysql table. Let me more clarify that I have two mysql tables as below,
table: monitor_servers
+-----------+-----------------+
| server_id | label |
+-----------+-----------------+
| 1 | a.com |
| 2 | b.com |
+-----------+-----------------+
table: monitor_servers_uptime
+-------------------+-----------+-----------+
| servers_uptime_id | server_id | latency |
+-------------------+-----------+-----------+
| 1 | 1 | 0.4132809 |
| 3 | 1 | 0.4157769 |
| 6 | 1 | 0.4194210 |
| 9 | 1 | 0.4140880 |
| 12 | 2 | 0.4779439 |
| 15 | 2 | 0.4751789 |
| 18 | 2 | 0.4762829 |
| 22 | 2 | 0.4706681 |
+-------------------+-----------+-----------+
Basically, each domains associated with the same id_number in both tables. While I am running the query below, getting average of each items.
select monitor_servers.label, avg(monitor_servers_uptime.latency)
from monitor_servers,monitor_servers_uptime
where monitor_servers.server_id = monitor_servers_uptime.server_id
group by monitor_servers.server_id;
The query ended up,
+---------------------+-------------------------------------+
| label | avg(monitor_servers_uptime.latency) |
+---------------------+-------------------------------------+
| a.com | 0.41393792995 |
| b.com | 0.47551423171 |
+---------------------+-------------------------------------+
My questions are doing am i in wright way while getting average of the each items and how can i insert new average result of each items into a new column on table monitor_servers ? And also what happens if some of latency rows are NULL ?
**Edit : What i am trying to achieve in one query result is **
+-----------+----------+------------------+
| server_id | label | avg. |
+-----------+----------+------------------+
| 1 | a.com | 0.41393792995 |
| 2 | b.com | 0.47551423171 |
+-----------+-----------------------------+
Thanks in advance,
Your calculation seems to be correct.
You could add another column to the monitor_servers using sql:
ALTER TABLE monitor_servers ADD avg_latency DEFAULT 0.0 NOT NULL
For doing the AVG calculation check this answer.