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.
Related
I have a two tables, one of the table is called participants_tb while the second is called allocation_tb. On the participants_tb, I have my columns as participant_id, name, username.
Under the allocation_tb, I have my columns as allocation_id, sender_username, receiver_username, done. The column done holds any of these three numbers: 0, 1, 2.
I used this sql statement to fetch my values
SELECT *, COUNT(done) d
FROM participants_tb
JOIN allocation_tb ON (username=receiver_username)
WHERE done = 0 || done = 1
GROUP BY receiver_username
It worked very well, the problem I have is that, I want it to also include the information of participants that are in the participants_tb but not in the allocation_tb. I tried to use the left outer join but it did not work as expected because I want it to include participants that are only in the participants_tb but not in the allocation_tb, since the done in the where clause is in the allocation_tb, it won't include those information.
You seem to want:
SELECT p.*, COUNT(a.done) as d
FROM participants_tb p LEFT JOIN
allocation_tb a
ON p.username = a.receiver_username) AND
a.done IN (0, 1)
GROUP BY p.participant_id;
Notes:
The LEFT JOIN keeps all participants.
The GROUP BY needs to be on the first table.
You can use SELECT p.* with the GROUP BY -- assuming that the GROUP BY key is unique (or the primary key).
All columns should be qualified.
IN is an easier way to express your logic.
I need to write a query to join 3 tables.
My tables are:
ucommerce_customer
ucommerce_order
ucommerce_order_line
All 3 tables have a column called order_id.
The table ucommerce_order has a column called order_status.
When the order_status is set to "open" I want to display the order details.
ResultSet myRs = myStmt.executeQuery
("SELECT * FROM ucommerce_customer
INNER JOIN ucommerce_order
INNER JOIN ucommerce_order_line
WHERE ucommerce_order.order_status = 'open'");
My query ignores the order status and displays all orders, open and closed.
Also I have several products so ucommerce_order_line has several entries for the same order_id, my query displays duplicate entries and it duplicates the entire list as well.
How can I write a query that will show only open orders without duplicating everything?
In MySQL, the on/using clause is optional. This is very sad because someone can make mistakes like you did. Your question only mentions one column, so perhaps that is all that is needed for the join:
SELECT *
FROM ucommerce_customer INNER JOIN
ucommerce_order
USING (orderId) INNER JOIN
ucommerce_order_line
USING (OrderId)
WHERE ucommerce_order.order_status = 'open';
I would be surprised if the customer table really had a column called OrderId (seems like a bad idea in most situations), so the first USING clause might want to use CustomerId.
I would recommend to use a natural join instead. Maybe that's where the errors are coming from.
The duplicates can be removed by running SELECT DISTINCT * ...
SELECT submissions.created_at, guests.accepted
FROM submission
INNER JOIN guests
ON guests.event_id = 1
ORDER BY submissions.created_at ASC;
Currently this query is taking a long time to run (may not even return everything).
What I am trying to accomplish:
Grab the field submissions.created at and guests.accepted (the two are linked by a submission_id)
given a certain event_id (event 1 for example).
What is wrong with my query?
You forgot to give the JOIN condition in your query. Try this:
SELECT submissions.created_at, guests.accepted
FROM submission s
INNER JOIN guests g on g.event_id = s.submissions_id
where guests.event_id = 1
ORDER BY submissions.created_at ASC;
SELECT submissions.created_at, guests.accepted
FROM submission
INNER JOIN guests
ON guests.(column to match against) = submissions.(column to match on)
where guests.event_id=1
ORDER BY submissions.created_at ASC;
As many others here have already said, your join is a little goofed. It's attempting to join the one row that matches in the guests table against every single row in the submission column.
You would need to do your join like this :
Inner join guest on guest.event_id = submissions_id
where guest.event_id = 1
When you join you need to join on two columns from different table (most of the time id columns)
You can read the MySQL example for more explanation. And here is the link to the MySQL reference manual
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
I just imported a large amount of data into two tables. Let's call them shipments and returns.
When trying to do a simple join (left or inner) based on any criteria in these two tables. query looks like it tries to do a cross join or find every combination instead of what the query should be pulling.
each table has an PK id field, but there is not FK relationship between the two other than some shared field.
I'm currently just trying to related them on shipment_id.
I feel this is a simple answer. Am I missing a reference or something obvious that is causing this? Thanks!
here's an example. This should returned under 100 rows. This instead returns hundreds of thousands.
SELECT r.*
FROM returns as r
left outer join shipments as s
on r.shipment_id = s.shipment_id
where r.date = '2011-06-20'
Here is a query that should work:
SELECT T0.*, T1.*
FROM shipments AS T0 LEFT JOIN returns AS T1 ON T0.shipment_id = T1.shipment_id
ORDER BY T0.shipment_id;
This query join assumes 1:1 on the shipment_id
It would be nice if you included the query you were using
You need to specify what you are joining on, otherwise it will do a cartesian join:
SELECT r.*
FROM returns as r
LEFT JOIN shipments as s ON s.shipment_id = r.shipment_id
where r.date = '2011-06-20'
Josh,
I would be interested in seeing what would happen if you forced a join to a specific record or set of records instead of the whole table. Assuming there is a shipment with an id of 5 in your table, you could try:
SELECT r.* FROM returns as r
left join shipments as s
ON 5 = r.shipment_id
WHERE r.date = '2011-06-20'
While just a fancy where clause, it would at least prove that the join you are attempting will eventually work correctly. The issue is that your on clause is always returning true, no matter what the value is. This could be because it's not interpreting the shipment_id as an integer, but instead as a true/false variable where any value evaluates to true.
Original Rejected Solution:
No Foreign Key relationship should be needed in order to make the joins happen. The PK id fields I'm assuming are an integer (or number, or whatever your rdms equivalent is)?
Can you past a snippet of your sql query?
Updating based on posted query:
I would add your explicit join criteria in order to rule out any funny business (my guess is since no criteria is specified, it's using 1=1, which always joins). So I would change your query to look like:
SELECT r.*
FROM returns as r
left join shipments as s ON
s.ShipId = R.ReturnId
where r.date = '2011-06-20'
The issue turned out to be very simple, just not readily apparent until going through all the columns. It turns out that the shipment ID was duplicated through every row as it hit the upper limit for the int datatype. This is why joins were returning every record.
After switching the datatype to bigint and reimporting, everything worked great. Thanks all for looking into it.