sqlalchemy order by left join with left outer on bottom - sqlalchemy

This query returns all users, and sorts them by which ones have the most recent message:
User.query.outerjoin(Message, Message.recipient_id == User.id).order_by(Message.created.desc())
The problem I am having is that this ordering places any users without messages on top. That is to say, it is ordering the left outer values on top. What I want is to see the left inner values (users with messages) on top. Does anyone know how to accomplish this with sqlalchemy?

Related

MySQL - Why does WHERE ignore RIGHT JOIN?

I have the following MySQL query:
SELECT inv.inventory_id, inv.item_id, item.description, inv.quantity, item.class_id, class.description AS class,
class.is_spool, inv.location_id, location.description AS location, location.division_id, division.name AS division,
inv.service_date, inv.reel_number, inv.original_length, inv.current_length, inv.outside_sequential,
inv.inside_sequential, inv.next_sequential, inv.notes, inv.last_modified, inv.modified_by
FROM reel_inventory AS inv
INNER JOIN reel_items AS item ON inv.item_id = item.item_id
INNER JOIN reel_locations AS location ON inv.location_id = location.location_id
INNER JOIN locations AS division ON location.division_id = division.location_id
RIGHT JOIN reel_classes AS class on item.class_id = class.class_id;
The query works exactly as expected as is. What I was trying to do was add a WHERE clause to this query with one qualifier. For example:
RIGHT JOIN reel_classes AS class ON item.class_id = class.class_id
WHERE inv.current_length > 0;
When I do this, all of the results from the RIGHT JOIN are not included in the result. I've not had a ton of experience with advanced queries, but could someone explain why the RIGHT JOIN is excluded from the result set when a WHERE is used, and how to property write the query to include the RIGHT JOIN information?
Thanks in advance.
What you want is:
RIGHT JOIN reel_classes AS class
ON item.class_id = class.class_id AND
inv.current_length > 0;
Your question is why the RIGHT JOIN turns into an INNER JOIN with the WHERE clause.
The reason is simple. For the non-matching rows, inv.current_length is NULL and this fails the comparison.
I would also suggest that you use LEFT JOIN, starting with the table where you want to keep all the rows. Most people find it much easier to understand logic that is "keep all rows in the first table" rather than "keep all rows in some table whose name will come up".

Mysql LEFT JOIN gives me result, RIGHT JOIN NOT also INNER JOIN

i trie to get results from two tables in my sql query. But all what i got, is the smaller table.
So the LEFT JOIN gives me the results from the smaller table, which holds only 5 columns.
The bigger one has about 25 columns. So if i trie to set the RIGHT JOIN, no results are shown. But also i got no error from mysql, just an empty result. Also the INNER JOIN dosen't work. Heres my query:
SELECT zu.*, peps.*
FROM audit.zusammen zu
RIGHT JOIN audit.pep peps
ON zu._id_fk = peps.id
WHERE MATCH (zu.concat_Names) AGAINST ('merkel' IN BOOLEAN MODE)
ORDER BY zu.last_Name
I assume that you mean row when you say column.
Also assuming that the big table is peps, I think that you want:
SELECT zu.*, peps.*
FROM audit.pep peps
LEFT JOIN audit.zusammen zu
ON zu.id_fk = peps.id
AND MATCH (zu.concat_Names) AGAINST ('merkel' IN BOOLEAN MODE)
ORDER BY zu.last_Name
This will produce as many record as there are in peps, with optional data coming from zusammen for records that match on id_fk and whose concat_Names satifsfy the full text seach on 'merkel'.
Recommended reading: What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

LEFT JOIN or INNER JOIN?

I have the following tables. All fields are NOT NULL.
tb_post
id
account_id
created_at
content
tb_account
id
name
I want to select the latest post along with the name. Should I use INNER JOIN or LEFT JOIN? From my understanding both produce the same results. But which is more correct or faster?
SELECT p.content, a.name
FROM tb_post AS p
[INNER or LEFT] JOIN tb_account AS a
ON a.id = p.account_id
ORDER BY p.created_at DESC
LIMIT 50
A LEFT JOIN is absolutely not faster than an INNER JOIN. In fact, it's slower; by definition, an outer join (LEFT JOIN or RIGHT JOIN) has to do all the work of an INNER JOIN plus the extra work of null-extending the results. It would also be expected to return more rows, further increasing the total execution time simply due to the larger size of the result set.
(And even if a LEFT JOIN were faster in specific situations due to some difficult-to-imagine confluence of factors, it is not functionally equivalent to an INNER JOIN, so you cannot simply go replacing all instances of one with the other!)
Better go for INNER JOIN.
As Per My View The Correct One Is Inner join
because it returns resultset that include only matched elements where Left Join Returns all entries from Left Table. In this case I think Inner join returns the only required amount of data to be proceed.
You have to ask yourself two questions.
1) Is there any chance that at some point in your application lifetime, there will be posts with an empty or invalid account_id?
If not, it doesn't matter.
If yes...
2) Would it be desirable to include posts without an associated account in the result of the query? If yes, use LEFT JOIN, if no, use INNER JOIN.
I personally don't think speed is very relevant: the difference between them is what they do.
They happen to give the same result in your case, but that does not mean they can be interchanged, because choosing the one or the other still tells the other guy that reads your code something.
I tend to think like this:
INNER JOIN - the two tables are basically ONE set, we just need to combine two sources.
LEFT JOIN - the left tables is the source, and optionally we may have additional information (in the right table).
So if I would read your code and see a LEFT JOIN, that's the impression you give me about your data model.

MySQL one to many data relationship with added complications

I have a database in which there are multiple posts. Each post can be associated with one or more location. Each location is then associated with one country.
This is handled through four tables:
post (with the id and post_title)
postlocation (with the fields post_id and location_id - to allow a one to many relationship)
location (with the fields id, location_title and country_id)
country (with the fields, id and country_title)
I want to perform a simple, effective select to retrieve a list of posts and each one's associated locations and each of those locations' country.
I'm at a loss as to how to best achieve this, and any help would be most welcome. Thank you.
Use LEFT JOIN:
SELECT post.*, location.*, country.*
FROM post
LEFT JOIN postlocation ON post.id = postlocation.post_id
LEFT JOIN location ON postlocation.location_id = location.id
LEFT JOIN country ON location.country_id = country.id
Here's an explanation of how LEFT JOIN works: http://www.mysqltutorial.org/mysql-left-join.aspx
The MySQL LEFT JOIN clause works like this: when a row from the left
table matches a row from the right table based on join_condition, the
row’s content are selected as an output row. When row in the left
table has no match it is still selected for output, but combined with
a “fake” row from the right table that contains NULL in all columns.
In short, the MySQL LEFT JOIN clause allows you to select all rows
from the left table even there is no match for them in the right
table.
When you have multiple LEFT JOINs, then in each case it uses the cumulative results so far as the "left" table and the table your are joining on as the "right" table.
So the query above will return one row for every post/location/country. Note that this means there will be potentially several rows with the same post.* data (one for each postlocation associated with taht post).
And if a post has no postlocations associated with it, that post will still show up in the results (but with null rows for location.* and country.*). Similarly, if a location has no country associated it with it, the post/location rows will still show up in the output (but with null rows for country.*). This is the advantage of LEFT JOIN -- you always get all the rows from the table on the "left".

How do I decide when to use right joins/left joins or inner joins Or how to determine which table is on which side?

I know the usage of joins, but sometimes I come across such a situation when I am not able to decide which join will be suitable, a left or right.
Here is the query where I am stuck.
SELECT count(ImageId) as [IndividualRemaining],
userMaster.empName AS ID#,
CONVERT(DATETIME, folderDetails.folderName, 101) AS FolderDate,
batchDetails.batchName AS Batch#,
Client=#ClientName,
TotalInloaded = IsNull(#TotalInloaded,0),
PendingUnassigned = #PendingUnassigned,
InloadedAssigned = IsNull(#TotalAssigned,0),
TotalProcessed = #TotalProcessed,
Remaining = #Remaining
FROM
batchDetails
Left JOIN folderDetails ON batchDetails.folderId = folderDetails.folderId
Left JOIN imageDetails ON batchDetails.batchId = imageDetails.batchId
Left JOIN userMaster ON imageDetails.assignedToUser = userMaster.userId
WHERE folderDetails.ClientId =#ClientID and verifyflag='n'
and folderDetails.FolderName IN (SELECT convert(VARCHAR,Value) FROM dbo.Split(#Output,','))
and userMaster.empName <> 'unused'
GROUP BY userMaster.empName, folderDetails.folderName, batchDetails.batchName
Order BY folderDetails.Foldername asc
Yes, it depends on the situation you are in.
Why use SQL JOIN?
Answer: Use the SQL JOIN whenever multiple tables must be accessed through an SQL SELECT statement and no results should be returned if there is not a match between the JOINed tables.
Reading this original article on The Code Project will help you a lot: Visual Representation of SQL Joins.
Also check this post: SQL SERVER – Better Performance – LEFT JOIN or NOT IN?.
Find original one at: Difference between JOIN and OUTER JOIN in MySQL.
In two sets:
Use a full outer join when you want all the results from both sets.
Use an inner join when you want only the results that appear in both
sets.
Use a left outer join when you want all the results from set a, but
if set b has data relevant to some of set a's records, then you also
want to use that data in the same query too.
Please refer to the following image:
I think what you're looking for is to do a LEFT JOIN starting from the main-table to return all records from the main table regardless if they have valid data in the joined ones (as indicated by the top left 2 circles in the graphic)
JOIN's happen in succession, so if you have 4 tables to join, and you always want all the records from your main table, you need to continue LEFT JOIN throughout, for example:
SELECT * FROM main_table
LEFT JOIN sub_table ON main_table.ID = sub_table.main_table_ID
LEFT JOIN sub_sub_table on main_table.ID = sub_sub_table.main_table_ID
If you INNER JOIN the sub_sub_table, it will immediately shrink your result set down even if you did a LEFT JOIN on the sub_table.
Remember, when doing LEFT JOIN, you need to account for NULL values being returned. Because if no record can be joined with the main_table, a LEFT JOIN forces that field to appear regardless and will contain a NULL. INNER JOIN will obviously just "throw away" the row instead because there's no valid link between the two (no corresponding record based on the ID's you've joined)
However, you mention you have a where statement that filters out the rows you're looking for, so your question on the JOIN's are null & void because that is not your real problem. (This is if I understand your comments correctly)