I'm working on Mysql to get the trending posts
I am joining four tables posts, posts_like, posts_shares, posts_comments and distinct the user_id of it. (post like, shares and comments should be added for total)
I am expecting a result of this for example only
RESULT:
post_id | user_id | count of shares, like, comments
---------------------------------------------------
1 | 2 | 50 |
8 | 5 | 47 |
---------------------------------------------------
table structure
table users
---------------------
id | username | etc |
---------------------
table posts
-------------------------------------
id | user_id | content | datecreated
-------------------------------------
post_likes
--------------------------------
id | post_id | user_id |
--------------------------------
post_shares
--------------------------------
id | post_id | user_id |
--------------------------------
comments
---------------------------------------
id | post_id | user_id | description |
--------------------------------------
user_id should be distinct
You could use left join and count distinct based group by p.id, p.user_id, u.username
select p.id as post_id, p.user_id, u.username
, count(distinct l.user_id)
, count(distinct s.user_id)
, count(distinct c.user_id)
, ifnull(count(distinct l.user_id),0) +
ifnull(count(distinct s.user_id),0) +
ifnull(count(distinct c.user_id),0) total
from post p
inner join users u on u.id = p.user_id
left join post_likes l on l.post_id = p.id
left join post_shares s on s.post_id = p.id
left join comments c on c.post_id = p.id
group by p.id, p.user_id, u.username
order by total desc
To get count of shares, like, comments, I suggest you to use UNION over these three tables.
Something like (check the syntax):
SELECT post_id, user_id, count(post_id) From (
SELECT post_id, user_id FROM post_likes
UNION
SELECT post_id, user_id FROM post_shares
UNION
SELECT post_id, user_id FROM comments) Group by post_id, user_id
Related
How can I group the statement by their user_id, i keep getting duplicates of 2 and 3 already used a group by on the user_id? What seems to be the error?
SELECT user_id, SUM(amount)
FROM users INNER JOIN
user_privileges
ON users.id = user_privileges.user_id
GROUP BY user_id, amount
ORDER BY user_id;
+---------+-------------+
| user_id | SUM(amount) |
+---------+-------------+
| 1 | 3000.00 |
| 2 | 2500.00 |
| 2 | 19000.00 |
| 3 | 2500.00 |
| 3 | 19000.00 |
| 4 | 12000.00 |
+---------+-------------+
The simple answer is to simply group by userid, not amount:
SELECT user_id, SUM(amount)
FROM users INNER JOIN
user_privileges
ON users.id = user_privileges.user_id
GROUP BY user_id
ORDER BY user_id;
However, the join does not even seem to be necessary. You can just do:
SELECT user_id, SUM(amount)
FROM user_privileges
GROUP BY user_id
ORDER BY user_id;
SELECT user_id, SUM(amount) FROM users
INNER JOIN user_privileges
ON users.id = user_privileges.user_id
GROUP BY user_id
ORDER BY user_id;
SELECT distinct (user_id), SUM(amount)
FROM users
INNER JOIN user_privileges
on users.id = user_privileges.user_id
GROUP BY user_id, amount
ORDER BY user_id;
I am trying to count the number of results in a column after joining a table and I am having a hard time getting my query to work.
In the end result, I need to get a table with the product id, product name and the number of medias for each product.
This is what I have so far:
SQL
select
p.id,
p.name,
count(distinct mp.media_id)
from products as p
left join medias_products as mp
on mp.product_id = p.id
group by mp.media_id
order by p.id
These are the tables:
Medias
Id | client id
------ | ---------
1 | 1
2 | 2
Products
id | name | client_id
------ | -------- | ---------
1 | product1 | 1
2 | product2 | 2
medias_products
product_id | media_id
---------- | --------
1 | 2
2 | 1
Client
id | name
------ | -----
1 | Peter
2 | John
In addition, I'd like to find another query that would give me the results filtered by an specific client id.
Can someone please shed some light and share the knowledge.
Thanks in advance.
Try this:
select
p.id,
min(p.name) as name,
count(distinct mp.media_id) as medias
from products as p
left join medias_products as mp
on mp.product_id = p.id
group by p.id
order by p.id
For your second query:
select
p.id,
min(p.name) as name,
count(distinct mp.media_id) as medias
from products as p
inner join medias_products as mp
on mp.product_id = p.id
inner join medias as m
on m.id = mp.media_id
inner join clients as c
on c.id = m.client_id
where c.id = <your client's id>
group by p.id
order by p.id
Shouldn't you GROUP BY p.id instead of mp.media_id? That is
select
p.id,
p.name,
count(distinct mp.media_id)
from
products as p
left join medias_products as mp
on p.id = mp.product_id
group by p.id
order by p.id
I have table named as posts
|id|user_id|title|description|
likes table like this
|id|user_id|post_id|
here is my sql code
select count(likes.id) as like_count, posts.* from `posts` left join
`likes` on `likes`.`post_id` = `posts`.`id` where `posts`.`status` = 'A'
group by `posts`.`id` order by `like_count` desc LIMIT 6
Here is the result
|like_count | id | user_id | title | description |
---------------------------------------------------
17 | 723 | 12 | ... | .... |
15 | 721 | 15 | ... | .... |
14 | 711 | 12 | ... | .... |
13 | 700 | 12 | ... | .... |
12 | 800 | 11 | ... | .... |
12 | 920 | 12 | ... | .... |
as you see user_id 12 is repeating thee times, I want only one post from one user.
Is there a way to select most liked post of each user, and make user_id don't repeat.
I'm aware this may not be the most efficient solution, but this is the first that came to my mind. Unfortunately, MySQL doesn't support window functions so the task is way harder and less elegant than the approach one would take using window functions.
Most liked posts of each user which will repeat user_id if there happens to be more than one post with equal number of likes and that number is the greatest for particular user:
select
user_likes.post_user_id,
user_likes.like_count,
p.id as post_id,
p.title,
p.description
from (
select
p.user_id as post_user_id,
MAX(l.like_count) as like_count
from posts p
inner join (select post_id, count(*) as like_count from likes group by post_id) l on p.id = l.post_id
group by p.user_id
) user_likes
inner join (select post_id, count(*) as like_count from likes group by post_id) l on user_likes.like_count = l.like_count
inner join posts p on l.post_id = p.id
If you really need one row per user then in case of ties in number of likes for different posts you need to pick a strategy to retrieve only one of those. For example you could take the one that was older by adding grouping on post_id and taking the min() of its value and joining back to posts table to retrieve it's title and description.
In this case modification of above script would look like:
select
most_liked_post.post_user_id,
most_liked_post.like_count,
most_liked_post.post_id,
p.title,
p.description
from (
select
user_likes.post_user_id,
user_likes.like_count,
MIN(l.post_id) AS post_id
from (
select
p.user_id as post_user_id,
MAX(l.like_count) as like_count
from posts p
inner join (select post_id, count(*) as like_count from likes group by post_id) l on p.id = l.post_id
group by p.user_id
) user_likes
inner join (select post_id, count(*) as like_count from likes group by post_id) l on user_likes.like_count = l.like_count
group by user_likes.post_user_id, user_likes.like_count
) most_liked_post
inner join posts p on most_liked_post.post_id = p.id
I need sql help for a query:
I want to create a view to list customers of a shop. This is a select of users table that have made 1 or more reservation (table reservations) OR have made 1 or more order (table shop_orders).
------------- --------------
| users: | | shops: |
------------- --------------
| id (PK) | | id (PK) |
------------- --------------
------------------ ----------------
| reservations: | | shops_orders:|
------------------ ----------------
| id (PK) | | id (PK) |
| user_id (FK) | | user_id (FK) |
| shop_id (FK) | | shop_id (FK) |
------------------ ----------------
This is my starting point working ok:
SELECT u.*,
r.shop_id,
(SELECT count(*)
FROM reservations r
WHERE r.user_id = u.id) AS num_reservations,
(SELECT count(*)
FROM shop_orders so
WHERE so.user_id = u.id) AS num_orders
FROM users u
INNER JOIN (SELECT r.user_id,
r.shop_id
FROM reservations r
UNION
SELECT so.user_id,
so.shop_id
FROM shop_orders so) AS r ON u.id = r.user_id
GROUP BY u.id
All the queries to this view will be filtered by shop_id, to show only the customers of a concrete shop (is the shop administration area).
And only select customers that have reservations OR orders (num_reservations > 0 OR num_orders > 0)
The problem i find is the performance: 2 counts(*) from entire tables. And also an union between these 2 entire tables.
Do you think in a better alternative approach i could test?
You can do it like this:
SELECT
u.*,
r.shop_id,
IFNULL(COUNT(DISTINCT r.id), 0) AS num_reservations,
IFNULL(COUNT(DISTINCT o.id), 0) AS num_orders
FROM users u
LEFT JOIN reservarions r ON r.user_id = u.id
LEFT JOIN shop_orders o ON o.user_id = u.id
GROUP BY u.id
HAVING num_reservations + num_orders > 0
Another way, should be quicker:
SELECT
u.*,
r.shop_id,
IFNULL(COUNT(DISTINCT r.id), 0) AS num_reservations,
IFNULL(COUNT(DISTINCT o.id), 0) AS num_orders
FROM users u
LEFT JOIN reservarions r ON r.user_id = u.id
LEFT JOIN shop_orders o ON o.user_id = u.id
WHERE r.id IS NOT NULL OR o.id IS NOT NULL
GROUP BY u.id
If you need to have it split by both users and stores they had used, do GROUP BY u.id, r.shop_id.
i am doing sql query to get values from db, db structure as follows...
fcats
| id | title | section |
+----+--------+---------+
| 1 | test | gd |
+----+--------+---------+
ftopics
| id | title | cat_id |
+----+--------+---------+
| 1 | test1 | 1 |
+----+--------+---------+
fposts
| id | post | topic_id |
+----+-------+----------+
| 1 | post | 1 |
+----+-------+----------+
I want to get total number of topics and posts for given category and using following query...
SELECT id, title (SELECT count(id) FROM ftopics WHERE cat_id = id) AS total_topics FROM fcats WHERE section = "gd"
and it gives correct results for total topics but how can i get total number of posts for all categories, i am abit confused about, please help me to write this query. thanks.
try this:
SELECT
t.id,
t.title,
COUNT(f.id) + COUNT(p.id) AS total
FROM fcats t
LEFT OUTER JOIN ftopics f
ON f.cat_id = t.id
LEFT OUTER JOIN fposts p
ON p.cat_id = t.id
WHERE t.section = "gd"
GROUP BY t.id, t.title
SELECT
t.id,
t.title,
COUNT(f.id) AS total_topics,
(SELECT COUNT(p.id) FROM fposts WHERE topic_id = t.id) total_posts
FROM fcats t
INNER JOIN ftopics f
ON f.cat_id = t.id
WHERE t.section = "gd"
GROUP BY t.id, t.title
not sure if this is the right syntax, updated the other answers code to try to answer your request for the two totals.