MYSQL many to many 3 tables query - mysql

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

Related

MySQL query - Select statement from two tables with group by returning records with largest ids

I really need help from you, I've spend a lot of time already on trying to figure it out but without success :(
I have two tables:
What I need is to group everything by sea_id / bat_season and gain the greatest Id's for these seasons. So bat_id's 3 & 5 should be returned with their linked data.
But if there is no data in Table 2 I still should see details of two seasons without Table 2 details.
My closest result is here with the below statement:
SELECT b.bat_id, b.bat_trophies, b.bat_ranking, s.sea_id, s.sea_name, s.sea_start
FROM gvg_seasons s
LEFT JOIN (SELECT bat_id, bat_trophies, bat_ranking, bat_season FROM gvg_battles ORDER BY bat_id DESC LIMIT 1) b
ON s.sea_id = b.bat_season
WHERE s.sea_gl_id = 1
GROUP BY s.sea_id DESC
The result:
Result
If someone can help me here please I will be very grateful.
I haven't tried this as I didn't fancy transcribing the table data from your images but it should provide the result you are looking for.
The innermost sub-query gets the max(bat_id) per bat_season. This is joined back to the gvg_battles to give the latest battle per season.
SELECT *
FROM gvg_seasons s
LEFT JOIN (
SELECT b1.*
FROM gvg_battles b1
JOIN (
SELECT bat_season, MAX(bat_id) AS max_bat_id
FROM gvg_battles
GROUP BY bat_season
) b_max ON b1.bat_id = b_max.max_bat_id
) b2 ON s.sea_id = b2.bat_season;

SQL Temporary Table or Select

I've got a problem with MySQL select statement.
I have a table with different Department and statuses, there are 4 statuses for every department, but for each month there are not always every single status but I would like to show it in the analytics graph that there is '0'.
I have a problem with select statement that it shows only existing statuses ( of course :D ).
Is it possible to create temporary table with all of the Departments , Statuses and amount of statuses as 0, then update it by values from other select?
Select statement and screen how it looks in perfect situation, and how it looks in bad situation :
SELECT utd.Departament,uts.statusDef as statusoforder,Count(uts.statusDef) as Ilosc_Statusow
FROM ur_tasks_details utd
INNER JOIN ur_tasks_status uts on utd.StatusOfOrder = uts.statusNR
WHERE month = 'Sierpien'
GROUP BY uts.statusDef,utd.Departament
Perfect scenario, now bad scenario :
I've tried with "union" statements but i don't know if there is a possibility to take only "the highest value" for every department.
example :
I've also heard about
With CTE tables, but I don't really get how to use it. Would love to get some tips on it!
Thanks for your help.
Use a cross join to generate the rows you want. Then use a left join and aggregation to bring in the data:
select d.Departament, uts.statusDef as statusoforder,
Count(uts.statusDef) as Ilosc_Statusow
from (select distinct utd.Departament
from ur_tasks_details utd
) d cross join
ur_tasks_status uts left join
ur_tasks_details utd
on utd.Departament = d.Departament and
utd.StatusOfOrder = uts.statusNR and
utd.month = 'Sierpien'
group by uts.statusDef, d.Departament;
The first subquery should be your source of all the departments.
I also suspect that month is in the details table, so that should be part of the on clause.

Cannot query a sum and compare the sum with another total in a mysql query

I want to check 2 databases to see if the money-payments are the same as the total. That is possible, but I get a very long table:
select
transaction_id
,total_low+total_high a
, sum(money_received) b
from
archive_transaction inner join archive_transaction_payment
on archive_transaction.id=archive_transaction_payment.transaction_id
group by transaction_id;
Actually I only want the transactions where the total is wrong!!
So now I want to add a!=b and that gives an invalid query. How to proceed?
Table archive_transaction has 1 row per transaction, but archive_transaction_payment can have multiple payments for one transaction. This makes it complicated for me.
select
transaction_id
,total_low+total_high a
, sum(money_received) b
from archive_transaction inner join archive_transaction_payment
on archive_transaction.id=archive_transaction_payment.transaction_id
where
a!=b
group by transaction_id;
Joins are still problematic for me, but I found an answer without join to find faults in the database.
SELECT id
FROM archive_transaction a
WHERE total_low + total_high != (SELECT Sum(money_received)
FROM archive_transaction_payment b
WHERE a.id = b.transaction_id);
Now I get a short list of problems in my database. Thanks for helping me out.

Retrieve last entry from one table based on query on another

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;

SQL Select - Some Rows Won't Display

I have two tables. One of them named files and there is al list of all files. the second table called payments, and there is in there a list of payments for some files.
Payments:
id | fileid | {...}
1 2
2 3
3 2
Files:
id | {...}
1
2
3
I want to select all files, and join the table payments to order by count of this table.
In this case, the first row will be file #2, because it repeats the most in the payments table.
I tried to do it, but when I do it - not all of the rows are shown!
I think it happens because not all of the files are in the payments table. So in this case, I think that it won't display the first row.
Thanks, and sorry for my English
P.S: I use mysql engine
** UPDATE **
My Code:
SELECT `id`,`name`,`size`,`downloads`,`upload_date`,`server_ip`,COUNT(`uploadid`) AS numProfits
FROM `uploads`
JOIN `profits`
ON `uploads`.`id` = `profits`.`uploadid`
WHERE `uploads`.`userid` = 1
AND `removed` = 0
ORDER BY numProfits
As others have noted you need to use LEFT JOIN. - This tells MySQL that entries from the tables to the left should be included even if no corresponding entries exists in the table on the right.
Also you should use GROUP BY to indicate how the COUNT should be deliminated.
So the SQL should be something like;
SELECT Files.ID, count(Payments.FileID) as numpays FROM
Files
LEFT OUTER JOIN
Payments
ON Files.id=Payments.FileID
GROUP BY files.ID
ORDER BY numpays desc
SQL Fiddle
Try this:
select B.fileid,A.{}.....
from
(select id,.....
from files A
inner join
(select count(*),fileid,.....
from payments
group by fileid) B
on files.id=payments.fileid)
I hope this helps. I'm assuming that all ID in files table are unique. In this answer, you can apply an order by clause as per your wish. I've left the select statement to you to select whatever data you want to fetch.
As far as your problem is described, I think this should work. If any problems, do post a comment.
Try LEFT JOIN - in MySQL, the default JOIN is actually an INNER JOIN. In an INNER JOIN, you will only get results back that are in both sides of the join.
See: Difference in MySQL JOIN vs LEFT JOIN
And, as noted in the comments, you may need a GROUP BY with your COUNT as well, to prevent it from just counting all the rows that come back.