sum price of childs in other table mysql - mysql

I have two table one store data child and parent hierarchy and other paths and descendant
+----------+------------+-----------+
| userid | parent | price |
+----------+------------+------------
| 1 | null | 20 |
| 2 | 1 | 20 |
| 3 | 1 | 20 |
| 4 | 2 | 20 |
| 5 | 2 | 20 |
| 6 | 3 | 20 |
| 7 | 4 | 20 |
+----------+------------+-----------+
I need to get all userid with parent 1 then get descendant in other table and group by userid sum prices
+-------------+---------------+-------------+
| ancestor_id | descendant_id | path_length |
+-------------+---------------+-------------+
| 1 | 1 | 0 |
| 1 | 2 | 1 |
| 1 | 3 | 1 |
| 1 | 4 | 2 |
| 1 | 5 | 2 |
| 1 | 6 | 2 |
| 1 | 7 | 3 |
| 2 | 2 | 0 |
| 2 | 4 | 1 |
| 2 | 5 | 1 |
| 2 | 7 | 2 |
| 3 | 3 | 0 |
| 3 | 6 | 1 |
| 4 | 4 | 0 |
| 4 | 7 | 1 |
| 5 | 5 | 0 |
| 6 | 6 | 0 |
| 7 | 7 | 0 |
+-------------+---------------+-------------+
I have query it sum all childs together
select
sum(b.price)
from webineh_prefix_nodes_paths_tmp a
join webineh_prefix_nodes_tmp b on (b.userid = a.descendant_id)
where a.ancestor_id = 1
this work fine but total sum parent 1
I need to show bellow result for child direct (2,3)
+----------+------------+-
| userid | total |
+----------+------------+
| 2 | 80 |
| 3 | 40 |
+----------+------------+
also in create sqlfiddle my question http://sqlfiddle.com/#!9/9415ed/2

Try this;)
select ancestor_id as userid, sum(b.price) as total
from webineh_prefix_nodes_paths_tmp a
join webineh_prefix_nodes_tmp b
on b.userid = a.descendant_id
where a.ancestor_id in (select userid from webineh_prefix_nodes_tmp where parent = 1)
group by ancestor_id
SQLFiddle Demo
Edited
select ancestor_id as userid, sum(b.price) as total
from webineh_prefix_nodes_paths_tmp a
join webineh_prefix_nodes_tmp b
on b.userid = a.descendant_id
inner join webineh_prefix_nodes_tmp c
on a.ancestor_id = c.userid
and c.parent = 1
group by ancestor_id
SQLFiddle Demo

try this
select sum(b.price) from webineh_prefix_nodes_paths_tmp a join webineh_prefix_nodes_tmp b on (b.userid = a.descendant_id) where a.ancestor_id in ( 1,2,3) GROUP by ancestor_id

Related

Inner Join for four tables is not working?

I have four tables mls_user, mls_category, mls_entry, and bonus_point.
Following are the tables:
mls_user
*--------------------------*
| id | store_id | name |
*--------------------------*
| 1 | 101 | Santosh |
| 2 | 101 | Aman |
| 3 | 102 | Ankit |
| 4 | 101 | Suman |
| 5 | 101 | Ramesh |
*--------------------------*
mls_category
*----------------------------------------*
| cat_no | store_id | cat_type | cat_val |
*----------------------------------------*
| 1 | 101 | running | 1 |
| 2 | 101 | cycling | 4 |
| 3 | 102 | running | 1 |
| 4 | 102 | swiming | 2 |
*----------------------------------------*
mls_entry
*----------------------------------------------------------*
| id | user_id | store_id | category | distance | status |
*----------------------------------------------------------*
| 1 | 1 | 101 | 1 | 5 | Approved |
| 2 | 1 | 101 | 1 | 10 | Approved |
| 3 | 1 | 101 | 2 | 50 | Approved |
| 4 | 1 | 101 | 1 | 10 | Approved |
| 5 | 2 | 101 | 1 | 5 | Approved |
*----------------------------------------------------------*
bonus_point
*---------------------------------------------------------*
| bns_id | user_id | store_id | bonus_points | bonus_type |
*---------------------------------------------------------*
| 1 | 1 | 101 | 100 | fixed |
| 2 | 2 | 101 | 25 | % |
*---------------------------------------------------------*
Now from these four tables, I want below output:
*--------------------------------------------------------------*
| name | points | bonus_points | bonus_type | Total_Points |
*--------------------------------------------------------------*
| Santosh | 25 | 100 | fixed | 125 |
| Aman | 5 | 25 | % | 30 |
| Suman | 0 | 0 | - | 0 |
| Ramesh | 0 | 0 | - | 0 |
| Ankit | 0 | 0 | - | 5 |
*--------------------------------------------------------------*
I am using the following query but this query only shows the value for Santosh and aman
SELECT u.id, u.name, COALESCE(t1.points, 0) AS points, b.bonus_points
FROM mls_user u
LEFT JOIN
(SELECT e.user_id, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c ON e.store_id = c.store_id AND e.category = c.cat_no
WHERE e.status='approved' AND e.store_id = '101'
GROUP BY e.user_id ) t1 ON u.id = t1.user_id
INNER JOIN bonus_points b ON b.user_id = u.id
WHERE u.store_id = '101'
ORDER by points DESC
So where I am doing wrong in my query, Please help me in this.
In your bonus_points table you have only two entry related to user 1 and 2 (Santosh and aman) if you use INNER JOIN then you obtain only these user
in this case you need left JOIN for bonus_points Too
SELECT u.id, u.name, COALESCE(t1.points, 0) AS points, ifnull(b.bonus_points,0) bonus_point
FROM mls_user u
LEFT JOIN (
SELECT e.user_id, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c ON e.store_id = c.store_id
AND e.category = c.cat_no
WHERE e.status='approved'
AND e.store_id = '101'
GROUP BY e.user_id
) t1 ON u.id = t1.user_id
LEFT JOIN bonus_points b ON b.user_id = u.id
WHERE u.store_id = '101'
ORDER by points DESC

Mysql Best way to query notifications like on stackoverflow

I have 4 tables:
comments
+----+-----------+--------------+-------+
| id | content | user_id | article_id |
+----+-----------+--------------+-------+
| 1 | Comment 1 | 2 | 5 |
| 2 | Comment 2 | 5 | 3 |
| 3 | Comment 3 | 1 | 6 |
| 4 | Comment 4 | 6 | 8 |
| 5 | Comment 5 | 1 | 6 |
| ...| ... | ... | ... |
+----------------+---------+------------+
votes
+----+----------+--------------+---+
| id | type | user_id | article_id |
+----+----------+--------------+---+
| 1 | 1 | 2 | 5 |
| 2 | 1 | 3 | 3 |
| 3 | 0 | 1 | 6 |
| 4 | 1 | 7 | 4 |
| 5 | 0 | 9 | 4 |
| 6 | 0 | 1 | 6 |
| ...| ... | ... | ... |
+------------+----------+----------+
notifications (object_id is the id of the vote|comment)
+----+----------+--------------+-------------+-------------+--------------+
| id | object_url| object_id |activitytype_id| sender_id | recipient_id |
+----+----------+------------+---------------+-------------+--------------+
| 1 | /../../.. | 1 | 2 | 2 | 6 |
| 2 | /../../.. | 2 | 2 | 3 | 2 |
| 3 | /../../.. | 1 | 1 | 2 | 7 |
| 3 | /../../.. | 2 | 1 | 5 | 2 |
| 3 | /../../.. | 3 | 1 | 1 | 3 |
| 3 | /../../.. | 3 | 3 | 1 | 2 |
| 3 | /../../.. | 4 | 2 | 7 | 8 |
| 3 | /../../.. | 5 | 3 | 9 | 1 |
| 3 | /../../.. | 6 | 3 | 1 | 5 |
| ...| ... | ... | ... | | |
+----+-----------+-----------+---------------+-------------+--------------+
activitytypes
+----+------------+
| id | label |
+----+------------+
| 1 | comment |
| 2 | vote up |
| 3 | vote down |
| ...| ... |
+-----------------+
I would like to get notifications like on stackoverflow.
I want to query the last notification (with comment content if the activity type is a comment or null if not) for every activitytype and object_url combinaison for a specific user.
For example I have 3 artiles A,B and C which all have 3 comments, 4 voteup and 2 votedown. How to get the last comment, voteup and votedown for every article ?
I have tried this query:
SELECT n.id, n.object_url , n.object_id, n.activitytype_id, IF(n.activitytypeId = 1,
(SELECT content FROM comments WHERE id=n.object_id), null) AS activitycontent
FROM notifications n WHERE n.recipient_id =1
GROUP BY n.activitytype_id,n.object_url
ORDER BY n.id DESC
But it doesn't work. Can anyone help ?
EDIT:
This following query in farhadamjady's answer gives me the first comment:
SELECT
n.id,
n.object_url,
n.object_id,
n.activitytype_id,
cm.content AS activitycontent
FROM
notifications n
LEFT OUTER JOIN `COMMENT` AS cm ON cm.id = n.object_id and n.activitytypeId = 1
WHERE
n.recipient_id = 1
GROUP BY
n.activitytype_id,
n.object_url
HAVING MAX(cm.id)
ORDER BY
n.id DESC
How can I change it to get the last ?
you should use left outer join like this :
SELECT
n.id,
n.object_url,
n.object_id,
n.activitytype_id,
cm.content AS activitycontent
FROM
notifications n
LEFT OUTER JOIN `COMMENT` AS cm ON cm.id = n.object_id and n.activitytypeId = 1
WHERE
n.recipient_id = 1
GROUP BY
n.activitytype_id,
n.object_url
HAVING MAX(cm.id)
ORDER BY
n.id DESC

How to count join on other table

How to count base on the others table sum
I have this tables
CARDS
| ID | Name |
---------------------
| 1 | Nice |
| 2 | Wow |
| 3 | Lol |
| 4 | Ohyeah |
| 5 | Olala |
VOTES
ID | *card_id* | *user_id* | vote |
-------------------------------------------------
1 | 1 | 1 | -1 |
2 | 2 | 2 | -1 |
3 | 2 | 4 | 1 |
4 | 2 | 5 | 1 |
5 | 3 | 2 | 1 |
6 | 3 | 1 | 1 |
RESULT QUERY WHAT I WANT
| card_id | total_votes |
-------------------------------
| 1 | -1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
and this is what I've tried
SELECT c.*, COALESCE(SUM(v.vote),0) as vote_count
FROM cards c
LEFT JOIN votes v ON c.id = v.card_id
I don't where I mistake, please need help
You dont need subquery, just the group by
SQL Fiddle Demo
SELECT c.`ID`,
COALESCE(Sum(v.vote), 0) AS total_votes
FROM cards c
LEFT JOIN votes v
ON c.id = v.`card_id`
GROUP BY c.`ID`;
OUTPUT
| ID | total_votes |
|----|-------------|
| 1 | -1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
You should select all votes and group them by card_id. There u can simply use SUM function.
SELECT c.id, COALESCE(SUM(v.vote), 0)
FROM VOTES
LEFT JOIN c ON v.card_id = c.ID
GROUP BY v.card_id
Following query will do the trick
select c.id, sum(v.vote)
from cards c, votes v
where c.id = v.card_id
group by c.id

select sum of product price for every 1 id productcategory

i want to find solution for my query problem. I need to find the SUM of all priceProduct*quantity and separated with each of productcategory. I have already made a query, but it takes longer time to executed it. this is my query,
SELECT
pb.ProductCategoryID,
pb.ProductCategoryDescription,
(SELECT
SUM((SELECT pd.HPP FROM `price details` pd WHERE pd.ProductID = pdt.ProductID ORDER BY pd.PriceDetailID DESC LIMIT 1)*
(SELECT StockProductBallance FROM `stock product` sp WHERE sp.ProductID = pdt.ProductID ORDER BY sp.StockProductID DESC LIMIT 1))
FROM product pdt
WHERE pdt.ProductCategoryID = pb.ProductCategoryID
) AS Total
FROM `product category` pb
GROUP BY pb.ProductCategoryID
this my example table
table product:
+------+-------+
| id_p | id_pc |
+------+-------+
| 1 | 3 |
| 2 | 4 |
| 3 | 3 |
| 4 | 4 |
+------+-------+
table productcategory:
+-------+---------+
| id_pc | pc_name |
+-------+---------+
| 3 | new_pc |
| 4 | old_pc |
+-------+---------+
table price details:
+---------------+------+-----+
| PriceDetailID | id_p | hpp |
+---------------+------+-----+
| 1 | 1 | 100 |
| 2 | 1 | 110 |
| 3 | 1 | 120 |
| 4 | 2 | 200 |
| 5 | 2 | 210 |
| 6 | 2 | 220 |
+---------------+------+-----+
table stockProduct:
+-----------------+------+---------------+
| id_stockProduct | id_p | stockballance |
+-----------------+------+---------------+
| 1 | 1 | 10 |
| 2 | 1 | 11 |
| 3 | 1 | 12 |
| 4 | 2 | 20 |
| 5 | 2 | 21 |
| 6 | 2 | 22 |
+-----------------+------+---------------+
Really need your help guys, for better query..

Limiting MySQL results based on a field

I've table called Products in that type is field type value might be any one of these values 1,2,3,4.
Now I'would like to get the result as
1. Group the results based on 'type'
2. And Limit the results for each group to 5.
How can I achieve this, Currently I'm using following query
SELECT
*,
(
(
CASE
WHEN product_title LIKE '%xyz%'
THEN 2
ELSE 0
END
) + (
CASE
WHEN product_description LIKE '%xyz%'
THEN 1
ELSE 0
END
)
) AS relevance
FROM
Products
WHERE (
(
product_title LIKE '%xyz%'
OR product_description LIKE '%xyz%'
)
)
AND product_available = 1
AND product_deleted <> 1
ORDER BY relevance DESC
SELECT * FROM products;
+------------+------+
| product_id | type |
+------------+------+
| 1 | 4 |
| 2 | 3 |
| 3 | 2 |
| 4 | 4 |
| 5 | 3 |
| 6 | 1 |
| 7 | 4 |
| 8 | 3 |
| 9 | 4 |
| 10 | 2 |
| 11 | 2 |
| 12 | 1 |
| 13 | 3 |
| 14 | 2 |
| 15 | 3 |
| 16 | 1 |
| 17 | 2 |
| 18 | 1 |
| 19 | 2 |
| 20 | 4 |
| 21 | 2 |
+------------+------+
SELECT x.*
FROM products x
JOIN products y
ON y.type = x.type
AND y.product_id <= x.product_id
GROUP
BY x.product_id
HAVING COUNT(*) <=3
ORDER
BY type
, product_id;
+------------+------+
| product_id | type |
+------------+------+
| 6 | 1 |
| 12 | 1 |
| 16 | 1 |
| 3 | 2 |
| 10 | 2 |
| 11 | 2 |
| 2 | 3 |
| 5 | 3 |
| 8 | 3 |
| 1 | 4 |
| 4 | 4 |
| 7 | 4 |
+------------+------+
Here's a simple one
SELECT
p.id,
p.type
FROM
Products p
WHERE
5 > (SELECT COUNT(id) from Products where id < p.id and type = p.type)
I have created the sqlfiddle for it, http://sqlfiddle.com/#!2/ab0c00/15