Retrieve last entry from one table based on query on another - mysql

I'm having trouble retrieving latest records from one table based on a query on another table. I've found many solutions which come close using the analogy of "last product ordered for each customer" but they are not perfect.
I have two tables with records linked using the field dailyrecno_i. I would like to retrieve the last entry into table 2 linked to this key.
The tables and desired output are as follows, any advice appreciated.

This is from MS SQL but this should give you an idea. Note that i only replicated your desired output from your sample data so i'm not sure if there is any condition that i missed.
SELECT [#table1].dailyrecno_i ,
MAX([moc_noteno_i]) ,
header ,
MAX([text])
FROM #table1
LEFT JOIN #table2 ON [#table1].dailyrecno_i = [#table2].dailyrecno_i
GROUP BY [#table1].dailyrecno_i ,
header;

I think this is the answer:
SELECT t1.dailyrecno_i, t2temp.moc_noteno_i, t1.header, t2temp.text from table1 t1 inner join (SELECT a.*
FROM table2 a
INNER JOIN (
SELECT dailyrecno_i, MAX(moc_noteno_i) moc_noteno_i
FROM table2
GROUP BY dailyrecno_i
) b ON a.dailyrecno_i = b.dailyrecno_i AND a.moc_noteno_i = b.moc_noteno_i) t2temp
on t1.dailyrecno_i = t2temp.dailyrecno_i group by t2temp.dailyrecno_i;

Related

In SQL when we join tables, is there a name for the new table?

E.g. in Pandas, we can apply a mask and create a new dataframe and assign it a name. Similarly in SQL, once I do a LEFT JOIN of 2 tables, is there a way to refer to the new combined table ?
You can join two table and can get the result in the new combined and also you can give name to that table . Just try this query and if get any doubt just feel free to ask anytime.
MYSQL QUERY
EMP(C1, C2, CD1)
DEPT(D1, D2)
SELECT NEWTABLE.First, NEWTABLE.Third
FROM
(SELECT E.C1 AS First, E.C2 AS Second, D.D2 AS Third FROM EMP E, DEPT D WHERE
E.CD1 = D.D1) NEWTABLE
WHERE NEWTABLE.Second > 20;
We have created a virtual table i.e "NEWTABLE" you can give your name also .
(SELECT E.C1 AS First, E.C2 AS Second, D.D2 AS Third FROM EMP E, DEPT D WHERE
E.CD1 = D.D1)
This is the query for where we have applied join query and also we have selected the three row from two table and renamed it as "FIRST", "SECOND" and "THIRD".
And you will get the doubt in the first line so let me clear we have performed the operation NEWTABLE.Second > 20;on the new table which we obtained after join.
If you still get any doubt regarding the query just ask .
Values Stored in the new table is temporary and you can use it for that query only.
And if you want to store permanent value then you have create to new table then assigned that table with the table we joined and so on .
No that won't work in sql, at least not directly
But you can do a subquery
Like
SELECT aa.*
FROM
(SELECT t1.*,t2.* FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.refid) aa
or A view
CREATE VIEW v AS SELECT t1.*,t2.* FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.refid;
A problem can result, when you have in both tables the same names for columns, that would cause problems, so you must check and in case of equal columnames alias the second column

Merging 2 tables preserving the ID

I have a question about merging a table with another preserving an ID on a database (I'm using MySQL). I have 2 tables, the first has and Item ID and a category and subcategory assigned to that ID. The second has a Item ID with all its characteristics like name and other variables. How can I merge those two tables in a way that the ID corresponds to the correct item in the new table (that's the difficult part I think)? Is it possible?
Thank you for all the help!
It's a very basic operation called Inner Join:
Select *
from table1
inner join table2
on table1.itemid = table2.itemid;
EDIT: As OP wants to create a new table with the fields return by above query and insert data into newly created table; following are the query to insert data once its created:
Insert into tablename
Select *
from table1
natural join table2;
Note: Make sure that the order and datatypes of columns in new table and in the result of above select query must be same.
I'm assuming you want to create table from the combined results. See this page for details.
Basically you write and test the SQL query then CREATE TABLE table_name AS sql_query
create table new_item_table
as
select
a.item_id,
a.category,
a.subcategory,
b.item_name,
b.item_char_1,
b.item_char_2
from
item_category a inner join item_char b on a.item_id = b.item_id;
This will Do:
select a.*,b.ItemName,b.ItemChar1,b.ItemChar2 from FirstTable a join select * from SecondTable b on a.ItemId=B.ItemId;
Use left join if some of the records are not there in the second table

select from database table rows that are not in another table

I have a table of 'entries' in a MYSQL database. I have another table that records activity on those entries, with the id of the entry as a foreign key. I want to select from my first table entries that do not appear in the second table.
How can I use SQL to make this happen? Do I have to iterate through both tables and compare every entry with every other entry? Is there an easier way to do this?
ex. I have a table with an entry data column and a user name column. I have another table with an entry id column and a user id column. I want to select from my first table all of the entries which do not appear in the second table with a given user id.
Thanks ahead of time. I have been struggling with this experiment for a while. I imagine I have to join the two tables somehow?
Several ways to achieve this, NOT IN, NOT EXISTS, LEFT JOIN / NULL check. Here's one with NOT EXISTS:
SELECT *
FROM FirstTable T
WHERE NOT EXISTS (
SELECT *
FROM SecondTable T2
WHERE T.Id = T2.Id
)
From what I understand, you want to select all rows where the foreign key doesn't match anything in the other table. This should do the trick:
SELECT *
FROM Data A
RIGHT JOIN Entry B
ON A.ID = B.ID
WHERE A.ID IS NULL
Here's a handy chart that illustrates how to use joins for stuff like this.
You can also use NOT IN, and the mechanics for this one are actually a bit easier to understand.
SELECT *
FROM Data A
WHERE A.ID NOT IN (SELECT ID FROM Entry)

Getting a string from a referenced table

I am relativly new to the SQL language. I can do a basic select, but for performance increase, I'd love to know if it is possible to merge the two queries I am doing at the moment into one.
Scenario: There are two tables. Table one has a few columns, one of them is a VARCHAR(45) named 'user', and another one is a INT which is called 'gid'. In the second table, there is a primary key column called 'gid' (INT) and a column called 'permissions' which is a TEXT column and it contains values seperated by ';'.
I have a user name, and want the text in the permissions column. The current way I do it is by fetching the gid of the first table, then doing a second query with the gid to get the permissions.
I've heard there are other ways to do this, and I have searched on Google, but I'm not sure what I should do.
EDIT:
Like this:
select t2.permissions
from table1 t1, table2 t2
where t1.user = '<SPECIFIED NAME>'
and t1.gid = t2.gid;
or you could use INNER JOIN syntax:
select t2.permissions
from table1 t1
inner join table2 t2 on t1.gid = t2.gid
where t1.user = '<SPECIFIED VALUE>'
To do this you use a JOIN. A join connects two tables in a select statement.
Like this
select *
from usertable u
join permissiontable p on u.gid = p.gid
This will give you all the columns from both tables with the id column joined. You can treat the joined table just like any table (eg select a sub-set of columns in the select list, add a where clause, etc).
You can read more about joins in any intro sql book or doing a google search.

MYSQL many to many 3 tables query

EDIT. I missed the one main issue I was having. I want to display all the unique 'device_MAC' rows. So I want this query to output 3 rows (as per the original query). The issue I am having is connecting the data table to the remote_node table via dt_short = rn_short where the maximum timestamp for dt_short in the data table.
I am having trouble running a query on 3 tables (2 have many to many relations).
What I am trying to do:
Get each distinct rn_IEEE from the remotenodes table with the maximum timestamp (in the example this will get 3 rows with 3 distinct short addresses rn_short)
Join with the devicenames table on device_IEEE
Get each distinct dt_short from the data table with the maximum timestamp
Join dt_short with rn_short from the query above
Now the problem I am running into is that I can do the queries for the above individually, I have even gotten the first 3 of them together into a query but I cannot seem to properly join the last bit of data to get the result that I want.
I have been going in circles trying to solve this. Here is a link to SQL Fiddle which contains all the test data and the query as far as I got it, it does what i want for the first line but from table 'data' after the first line is NULL:
See this SQL fiddle
After going through your requirements and the data, it looks like you just need to change your query to include an INNER JOIN on the data table instead of a LEFT JOIN
See SQL Fiddle with Demo
select rn.*, dn.*, d.*
from remotenodes rn
inner join devicenames dn
on rn.rn_IEEE = dn.device_IEEE
and rn.rn_timestamp = (SELECT MAX(rn_timestamp) FROM remotenodes
WHERE rn.rn_IEEE = rn_IEEE
GROUP BY rn_IEEE)
inner join data d
on rn.rn_short = d.dt_short
AND d.dt_timestamp = (SELECT MAX(d2.dt_timestamp) AS ts
FROM data d2
WHERE d.dt_short = d2.dt_short
GROUP BY d2.dt_short)
what you have done the query in your SQL fiddle is right.Instead of using left join use inner join so that it will give you the first row
cheers.
Thanks for all your answers everyone. I managed to solve the problem by using views.
It's not the most efficient way but I think it will do for now.
Here is the SQL Fiddle link:
http://sqlfiddle.com/#!2/4076e/8
Try this query, for me its returning one row:
SELECT rn_short, rn_IEEE, device_name
FROM
(SELECT DISTINCTROW dt_short FROM (SELECT * FROM `data` ORDER BY `dt_timestamp` DESC) as data ) as a
JOIN
(SELECT rn_IEEE, rn_short, device_name FROM devicenames dn JOIN (SELECT DISTINCTROW rn_IEEE, rn_short FROM (SELECT * FROM `remotenodes` ORDER BY `rn_timestamp` DESC) as remotenodes GROUP BY rn_IEEE) as rn ON dn.device_IEEE = rn.rn_IEEE) as b
ON a.dt_short = b.rn_short