mysql return one row of right table - mysql

I am facing a huge problem with MYSQL.
I have a table called tperson with the following content
+--------------+------------+
| tperson_id | first_name |
+--------------+------------+
| 1 | juan |
| 2 | miguel |
| 3 | Carlos |
| 4 | Diego |
+--------------+------------+
on the second table i have this data
+--------------+------------+------------+
| tperson_id | trans_code | date_added |
+--------------+------------+------------+
| 1 | 2000-01 |2020/03/03 |
| 1 | 2000-02 |2020/03/04 |
| 2 | 1999-05 |2019/12/25 |
| 3 | 1999-06 |2019/12/26 |
| 3 | 1999-07 |2019/12/27 |
+--------------+------------+------------+
Now I want to have this result in mysql
+--------------+------------+------------+------------+
| tperson_id | first_name | trans_code | date_added |
+--------------+------------+------------+------------+
| 1 | juan |2000-02 | 2020/03/04 |
| 2 | miguel |1999-05 | 2019/12/25 |
| 3 | Carlos |1999-07 | 2019/12/27 |
| 4 | Diego | null | null |
+--------------+------------+------------+------------+
what is the right MYsql statement to generation the result I want?
pls anyone help, I keep looking for the answer found nowhere. I am not good in any database.
thank you so much

I'm assuming your 2nd table name is tdate, and data on trans_code and date_added that's being selected is the latest value if there are more than one data from the same tperson_id on table tdate
SELECT tp.tperson_id, tp.first_name, MAX(td.trans_code), MAX(td.date_added)
FROM tperson tp
LEFT JOIN tdate td
ON tp.tperson_id = td.tperson_id
GROUP BY tp.tperson_id

Related

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 - Join tables and convert rows to columns

I have two tables similar to these (t_stamp would normally be a DATETIME, abbreviated here for clarity):
datapoints
+------+---------+----+---------+
| ndx | value | ID | t_stamp |
+------+---------+----+---------+
| 1 | 503.42 | 1 | 3/1/15 |
| 2 | 17.81 | 2 | 3/1/15 |
| 4 | 498.21 | 1 | 3/2/15 |
| 4 | 19.51 | 2 | 3/2/15 |
+------+---------+----+---------+
parameters
+------+----+---------------+-------+
| ndx | ID | description | unit |
+------+----+---------------+-------+
| 1 | 1 | wetwell level | ft |
| 2 | 2 | effluent flow | MGD |
+------+----+---------------+-------+
I'm looking to combine them so that the descriptions become column headers and list the values in order of time stamp, end result looking something like this:
new table
+---------+---------------+---------------+
| t_stamp | wetwell level | effluent flow |
+---------+---------------+---------------+
| 3/1/15 | 503.42 | 17.81 |
| 3/2/15 | 498.21 | 19.51 |
+---------+---------------+---------------+
Bearing in mind, I have considerably more rows in each table so I'm looking for something dynamic. It could be query or stored procedure based. Thank you for any help!

Remove duplicates SQL while ignoring key and selecting max of specified column

I have the following sample data:
| key_id | name | name_id | data_id |
+--------+-------+---------+---------+
| 1 | jim | 23 | 098 |
| 2 | joe | 24 | 098 |
| 3 | john | 25 | 098 |
| 4 | jack | 26 | 098 |
| 5 | jim | 23 | 091 |
| 6 | jim | 23 | 090 |
I have tried this query:
INSERT INTO temp_table
SELECT
DISTINCT #key_id,
name,
name_id,
#data_id FROM table1,
I am trying to dedupe a table by all fields in a row.
My desired output:
| key_id | name | name_id | data_id |
+--------+-------+---------+---------+
| 1 | jim | 23 | 098 |
| 2 | joe | 24 | 098 |
| 3 | john | 25 | 098 |
| 4 | jack | 26 | 098 |
What I'm actually getting:
| key_id | name | name_id | data_id |
+--------+-------+---------+----------+
| 1 | jim | 23 | NULL |
| 2 | joe | 24 | NULL |
| 3 | john | 25 | NULL |
| 4 | jack | 26 | NULL |
I am able to dedupe the table, but I am setting the 'data_Id' value to NULL by attempting to override the field with '#'
Is there anyway to select distinct on all fields and while keeping the value for 'data_id'? I will take the highest or MAX data_id # if possible.
If you only want one row returned for a specific value (in this case, name), one option you have is to group by that value. This seems like a good approach because you also said you wanted the largest data_id for each name, so I would suggest grouping and using the MAX() aggregate function like this:
SELECT name, name_id, MAX(data_id) AS data_id
FROM myTable
GROUP BY name, name_id;
The only thing you should be aware of is the possibility that a name occurs multiple times under different name_ids. If that is possible in your table, you could group by the name_id too, which is what I did.
Since you stated you're not interested in the key_id but only the name, I just excluded it from the query altogether to get this:
| name | name_id | data_id |
+-------+---------+---------+
| jim | 23 | 098 |
| joe | 24 | 098 |
| john | 25 | 098 |
| jack | 26 | 098 |
Here is the SQL Fiddle example.
RENAME TABLE myTable to Old_mytable,
myTable2 to myTable
INSERT INTO myTable
SELECT *
FROM Old_myTable
GROUP BY name, name_id;
This groups my tables by the values I want to dedupe while still keeping structure and ignoring the 'Data_id' column

MySQL - Use Header Name as Part of Query Filter

I'm relatively new to MySQL and have come across a problem to which I cannot seem to find a solution. I have searched but could not find an answer. I'm open to the possibility that I'm not asking the question correctly. Here goes:
I'm trying to use the name of a given column and the values within that column from one table to pull values from another table. The first table contains 3 columns with the response codified. The second table contains the definitions for each code for each item. The same number code is associated with different meanings depending on the item. For example:
table1 (this table cannot change):
--------------------------------------------------------------
|result_id | f_initial | l_name | item_A | item_B | item_C |
--------------------------------------------------------------
| 1 | j | doe | 1 | 3 | 2 |
| 2 | k | smith | 3 | 1 | 2 |
| 3 | l | williams | 2 | 2 | 1 |
--------------------------------------------------------------
table2 (this table can be modified, split, or whatever needs to be done):
-------------------------------------------
|item_id | item_name | score | definition |
-------------------------------------------
| 1 | item_A | 1 | agree |
| 2 | item_A | 2 | neutral |
| 3 | item_A | 3 | disagree |
| 4 | item_B | 1 | likely |
| 5 | item_B | 2 | not likely |
| 6 | item_B | 3 | no reply |
| 7 | item_C | 1 | yes |
| 8 | item_C | 2 | no |
-------------------------------------------
My goal is for the query to output the following:
--------------------------------------------------------------------
|result_id | f_initial | l_name | item_A | item_B | item_C |
--------------------------------------------------------------------
| 1 | j | doe | agree | no reply | no |
| 2 | k | smith | disagree | likely | no |
| 3 | l | williams | neutral | not likely | yes |
--------------------------------------------------------------------
Any assistance or guidance is greatly appreciated. Thank you in advance.
You must join the two tables on the item_A/B/C and score columns
select t1.result_id, t1.f_initial, t1.l_name,
t2a.definition as item_a,
t2b.definition as item_b,
t2c.definition as item_c
from table1 t1
join table2 t2a on t2a.score = t1.item_a
join table2 t2b on t2b.score = t1.item_b
join table2 t2c on t2c.score = t1.item_c
where t2a.item_name = 'item_A'
and t2b.item_name = 'item_B'
and t2c.item_name = 'item_C'

Correct method to optimise MySQL query

I've been struggling with a query which selects from multiple tables. My original query was incredibly slow (53 seconds). From reading up, I'm now reasonably sure that I need to create an inner query to limit the data which is iterated over. But I'm not sure how to use the result of the subquery (inner query) when using more than 2 tables. Below are some dummy tables:
+-------+---------------------+------------+
| tr_id | tr_datecreated | tr_depart |
+-------+---------------------+------------+
| 1 | 2011-07-31 00:00:00 | 2011-08-20 |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 |
+-------+---------------------+------------+
+------+--------+---------+---------+
| p_id | p_trid | p_name | p_lname |
+------+--------+---------+---------+
| 1 | 1 | Geoff | Thingy |
| 2 | 1 | Mildred | Thingy |
| 3 | 1 | Garry | Thingy |
| 4 | 2 | Linda | Doobrey |
| 5 | 2 | Kev | Doobrey |
| 6 | 3 | John | Wotsit |
| 7 | 3 | Jill | Wotsit |
+------+--------+---------+---------+
+------+--------+----------+
| h_id | h_trid | h_dest |
+------+--------+----------+
| 1 | 1 | France |
| 2 | 1 | Spain |
| 3 | 2 | Italy |
| 4 | 3 | Portugal |
+------+--------+----------+
I want to get a result such as:
+-------+---------------------+------------+---------+---------+----------+
| tr_id | tr_datecreated | tr_depart | p_name | p_lname | h_dest |
+-------+---------------------+------------+---------+---------+----------+
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | Spain |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | Spain |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | Spain |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 | Linda | Doobrey | Italy |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 | Kev | Doobrey | Italy |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 | John | Wotsit | Portugal |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 | Jill | Wotsit | Portugal |
+-------+---------------------+------------+---------+---------+----------+
where we get a separate row for each person for each holiday destination.
My original effort was in the form of:
SELECT tr_id, tr_datecreated, tr_depart, p_name, p_lname, h_dest
FROM transaction, people, holiday
WHERE tr_id = p_trid
AND tr_id = h_trid
AND tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00:00"
I think that this created a huge number of cross joins and the query ran very slowly.
Seeing as the tr_id is being referenced a number of times I wanted to do an inner query which reduced the number of rows that everything else was compared to.
So the inner query part will be:
SELECT tr_id WHERE tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00:00"
How would I create my desired table which I would want to compare both the p_trid and the h_trid against the same inner query without running that inner query twice (if possible)?
Would inner joins help in this situation? (I have read through but haven't fully absorbed it yet).
Grateful for any advice and suggestions here. The database is large and I need to be efficient.
Edit
Indexes:
tr_id, h_id and p_id are all primary keys
Result of EXPLAIN
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
| 1 | SIMPLE | holiday | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | people | ALL | NULL | NULL | NULL | NULL | 7 | Using where; Using join buffer |
| 1 | SIMPLE | transactions | eq_ref | PRIMARY | PRIMARY | 4 | db.people.p_trid | 1 | Using where |
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
I think that this should work. Let me know if it works.
Total Query
SELECT t.id, t.date, t.depart, p.p_name, p.p_lname, h.h_dest
FROM
(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00")
AND DATE("2012-12-12 00:00:00")) t
JOIN people p ON t.id = p.p_trid
JOIN holiday h ON t.id = h.h_trid;
Inner Query
(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00")
AND DATE("2012-12-12 00:00:00"))
Edit: Subquery explanation
The subquery selects the id, date created, and depart columns from the transaction table for the date range that you listed above. The 't' outside the right paren at the end of query lets you alias the inner query so you can use its data above. Also, where I have 'id','date', and 'depart' inside the subquery is also aliasing. It lets you use those values without typing out the full column name.
Hope this helped.
have you tried joins?
SELECT tr.tr_id, tr.tr_datecreated, tr.tr_depart, p.p_name, p.p_lname, h.h_dest
FROM transaction tr
join people p on tr.tr_id = p.p_trid
join holiday h on tr.tr_id = h.h_trid
WHERE tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00
haven't tested this yet but that's the general idea.
I suggest to add an index on people.p_trid and holiday.h_trid. The EXPLAIN clearly shows that there is no index used for both tables.
Also make sure that datatype of transactions.tr_id, people.p_trid and holiday.h_trid is the same.