SQLite Join - query most recent posts by each user - sqlite

In a sqlite database i have a "Users" table as follows
Users:
| user_id | user
| 1 | John
| 2 | Peter
a "Posts" table as follows:
| post_id | user_id | text
| 10 | 1 | blah blah blah
| 11 | 1 | blah blah blah
| 12 | 2 | blah blah blah
I'm using this code to join two tables:
SELECT * FROM Users JOIN Posts USING ( user_id )
Now i have a list of all posts by different users as follows:
| user_id | user | post_id | text
| 1 | John | 10 | blah blah blah
| 1 | John | 11 | blah blah blah
| 2 | Peter | 12 | blah blah blah
Assuming that the post with bigger post_id is posted more recently.
Now i want a list of most recent posts by each users (row #2 and #3 in this case).
How can i do this?
I'm thinking of deleting all rows (for each users) , except the rows which has biggest post_id (most recent), is this a good solution? how should i query it?

You can use an inner query that gets you the latest post for each user, then that table will act as a filter when joined with the other two.
select *
from users u
join (
select user_id, max(post_id) post_id
from Posts
group by user_id
) r
on u.user_id = r.user_id
join posts p
on r.post_id = p.post_id and
r.user_id = p.user_id

In SQLite (but not in any other DB), when using GROUP BY, you can use max() or min() to select which row to return in a group:
SELECT user_id,
user,
max(post_id) AS post_id,
text
FROM Users
JOIN Posts USING ( user_id )
GROUP BY user_id;

you have to change the query a little bit. you have to write the query as follows:
SELECT * FROM Users Join Posts Using(user_id) order by post_id desc;

Related

Doctrine - Left Join with LIMIT

I Have two tables : Post and Comment in a Many to One relation.
table post table comment
p_id | name | u_id c_id | p_id | comment | date
1 | post 1 | 1 1 | 1 | blah blah blah | 2017-01-01
2 | post 2 | 2 2 | 1 | blah blah blah | 2017-01-04
3 | post 3 | 1 3 | 2 | blah blah blah | 2017-01-07
... ...
I would like to retrieve all Posts by u_id with their 3 Last comments ordered by date.
I would do :
SELECT p, c
FROM p
LEFT JOIN p.comments c WITH c.date IN (SELECT c2.date) FROM App\Bundle\Entity\Comment as c2 WHERE c2.post = p.p_id ORDER BY date ASC LIMIT 3)
WHERE p.user = 1
But doctrine doesn't allow LIMIT, how i can do that ?
In my opinion the easiest way to to that is by using the function
setMaxResults($limit);
I give you an example :
$qb = $this->createQueryBuilder('a');
$qb
->innerJoin('a.advert', 'adv')
->addSelect('adv')
;
$qb->setMaxResults($limit);
return $qb
->getQuery()
->getResult()
I hope it will help you
As I known QueryBuilder::setMaxResult() work only on primary table not on subquery.
IMHO it's best to write it in classic SQL, where you have better control on subquery and what is joining. In this case you get plain array not array of objects with relation. But, this is better when you need only to show lists of posts and not interact with single entity. In this case getting entire object hydrating one by one populating from DQL, is quite slower then using plain array from SQL.
You could do this like that:
$conn = $this->getEntityManager()->getConnection();
$stmt = $conn->prepare('SELECT ...');
$stmt->execute($parameters);
$results = $stmt->fetchAll(\PDO::FETCH_ASSOC);

Join a query result set with an existing table in sqlite?

I have a query result set like this:
value | id
500 | 1
400 | 1
300 | 2
and a product table:
product_name | id
product_1 | 1
product_2 | 2
product_5 | 3
product_6 | 4
product_9 | 5
product_0 | 6
Now I want to find the product_name from product table for every row in query result set and join the result to look like following:
The result after joining should be following:
product_name | id | value
product_1 | 1 | 500
product_1 | 1 | 400
product_2 | 2 | 300
I am getting confused how to use left join to achieve the result.
You'd join based on the value that's common between the two tables; in this case, it's id.
It doesn't seem like you want any NULL values for value, so you wouldn't use a LEFT JOIN; you'd want an INNER JOIN instead.
This would get you pretty much what you want; bear in mind that this is untested.
SELECT p.product_name, qr.id, value
FROM product p
INNER JOIN query_result_set qr ON qr.id = p.id
ORDER BY value DESC;
Also, your expectations are wrong - product_5 has an id of 3, so it wouldn't appear in this join result.

SQL Query for Parent Child Data from two table

I have 2 table one table is Course Category and second is Course
In Course Category Table
Following data stores :
CategoryId | Name
1 | MCA
2 | MBA
In Course Table
Following data stores :
Id | Name | CategoryId | ParentId
1 | Asp.Net | 1 | 0
2 | C# | 1 | 1
3 | Finance | 2 | 0
i want following output
Id | Name | Parent
1 | MCA | 0
2 | MBA | 0
3 | Asp.Net | 1
4 | C# | 3
5 | Finance | 2
Whether i have to use nested query or should i relate two tables with foreign and primary keys or any mapping should be done.if not give me a solution to do this.
thanks in advance
select rownum as id, name, 0 as parent
from Category
union all
select rownum, name, id
from course
I assume that you only have one level of children (no cases like parent<-child<-child)
select c.id, t.name, parent.name, c.name from course c
join category t on c.categoryId = t.id
left join (select c2.id, c2.name from course c2) parent on c.parentId = parent.id
This should give you something like
id |categoryname |parentname |coursename
1 |MCA |null |Asp.Net
2 |MCA |Asp.Net |C#
3 |MBA |null |Finance
This is not exactly your desired result but should do the trick to display what you want.

select record that match one item in column

So I'm making a movie website and in my database table, I've got a column called Genre. In this I have listed the genres like this; Horror, Action.
Example Table
+----+---------+--------+
| id | Genre |
+----+---------+--------+
| 1 | Action |
| 2 | Horror, Action |
| 3 | Horror |
| 4 | Action |
| 5 | Romance, Drama |
| 6 | Horror, Drama |
+----+---------+--------+
So if I were to do a query to get films with a Horror genre, it would return the ID's 2,3 & 6. How would I go about structuring a query to do this?
Thanks.
The structure of your database is no good. Read up on database normalization to understand why this is. I would go with a structure like this:
Movie:
Id
Name
Movie_Genres
Movie_Id
Genre_Id
Genres:
Id
Name
You can then do a query like this:
SELECT m.name
FROM Movie as m
INNER JOIN Movie_Genres as mg
ON mg.Movie_id = m.id
WHERE mg.Genre_id = {Horror genre Id}
If you don't structure your DB like this you will run into a lot of problems down the road.
Continuing off of #Abe's excellent answer. If you want to build a comma delimited string based on #Abe's normalized 3 table structure it would look like this:
SELECT m.Name,
STUFF(( SELECT ', ' + g.Name
FROM Movie_Genres as mg
INNER JOIN Genres AS g on mg.Genre_id = g.Id and mg.Movie_id = m.id
FOR XML PATH('')
), 1, 2, '')
FROM Movie AS m
GROUP BY m.Name, m.Id;
Here's a Fiddle

How to Display doctors ordered by number of performed surgeries

I have table [Surgery_By] table[Surgery] table[Doctor] i'm using ASP.NET with SQL Server :
The table [Surgery_By] contains the following columns:
1-ID (PK)
2-Surgery ID (FK)
3-Doctor ID (FK)
How to Display doctors ordered by number of performed surgeries ?
Try it this way
SELECT d.id, d.fullname, COUNT(s.id) total_surgeries
FROM doctor d LEFT JOIN surgery_by s
ON d.id = s.doctor_id
GROUP BY d.id, d.fullname
ORDER BY total_surgeries DESC
Sample output:
| ID | FULLNAME | TOTAL_SURGERIES |
|----|------------|-----------------|
| 1 | John Doe | 3 |
| 2 | Jane Doe | 1 |
| 3 | Mark Smith | 0 |
Here is SQLFiddle demo
This is a stab in the dark.
Select Doctor.ID As DoctorID
,Count(*) As Count
From Doctor
Join Surgery_By
On Doctor.ID = Surgery_By.DoctorID
Group By Doctor.DoctorID
Order By Count(*)
I am not sure if you want the table Surgery incorporated (but if you do, the join will be pretty straight forward - just be sure to add selected columns to the Group By statement.)
From ASP.NET, you may select this data from a SQL Command.

Resources