Group by gives wrong title - mysql

I've got this database structure:
id | parent_id | name | num_begin | num_changes
====|===========|============|===========|=============
1 | 1 | 0001-0001 | 10 | 0
2 | 2 | 0001-0002 | 15 | 2
3 | 3 | 0001-0003 | 20 | 0
4 | 3 | testgroup | 5 | 1
The user can make groups and subgroups. The subgroup get's a parent_id. The testgroup in the above table is a subgroup of 3.
Now I want to select the current numbers (num_begin - num_changes). So I made this query:
SELECT
name,
( SUM( num_begin ) - SUM( num_changes ) ) AS num_now
FROM
groups
GROUP BY
parent_id
ORDER BY
id DESC
The result is:
name | num_now
============|===========
0001-0001 | 10
0001-0002 | 13
testgroup | 24
But I would like to have the name of the original group. So instead of testgroup it should be 0001-0003
Any thoughts?

Do a join on parents:
select p.name,
sum(c.num_begin) - sum(c.num_changes) as num_now
from groups c
join groups p on c.parent_id = p.id
group by p.id, p.name
When joining on parent you are getting the following results:
---------------------c-------------------------- | ----------p-------------...
id parent_id name num_begin num_changes | id parent_id name
1 1 0001-0001 10 0 | 1 1 0001-0001
2 2 0001-0002 15 2 | 2 2 0001-0002
3 3 0001-0003 20 0 | 3 3 0001-0003
4 3 testgroup 5 1 | 3 3 0001-0003
No you are grouping by p and calculating c.

Related

SUM() counts row twice and displaying double result

Why SUM() counts row twice and displaying double of actual result in here ?
Here I m trying to count total rows of status that has 0 value from the inv_id table of each student (inv_id.s_id) .
it has to show 4 based on the row number in inv_lst table but here it is showing 8.
If fee.id is GROUP_BY then it shows actual SUM but same student id starts to duplicate.
Please see fiddle - SQL Fiddle
Database Structure
class
id | ttl
===========
1 | One
2 | Two
section
id | ttl
===========
1 | A
2 | B
fee
id | ttl
===============
1 | Annual
2 | Monthly
student
id | ttl | cls | sec
===========================
1 | John| 1 | 1
2 | Paul| 1 | 1
3 | Rina| 2 | 1
sec_fee
id | c_id| s_id| f_id| fee
===================================
1 | 1 | 1 | 1 | 1000
2 | 2 | 1 | 2 | 560
inv_id
id | s_id| ft_id | status
==================================
1 | 1 | 1 | 0
2 | 1 | 2 | 0
3 | 1 | 3 | 0
4 | 1 | 4 | 0
Mysql
SELECT
student.id, student.ttl AS stdt,
cls.ttl AS cls,
sec.ttl AS sec,
GROUP_CONCAT(DISTINCT fee.id, '.', fee.ttl, '-', sec_fee.fee,'<br/>' ORDER BY sec_fee.f_id) AS amnt,
SUM(inv_id.status=0) AS upad,
SUM(inv_id.status=1) AS pad
FROM
student
JOIN
cls ON cls.id=student.cls
LEFT JOIN
sec ON sec.id=student.sec
LEFT JOIN
inv_id ON inv_id.s_id = student.id
LEFT JOIN
sec_fee ON sec_fee.c_id = student.cls
LEFT JOIN
fee ON fee.id = sec_fee.f_id
WHERE
cls.id = 1

How to use Mysql SUM with JOIN

I have the following tables:
purchase_tbl
id | productId | purchaseQuantity
---+-----------+-----------------
1 | 1 | 30
2 | 2 | 30
3 | 1 | 10
4 | 2 | 10
sale_tbl
id | productId | saleQuantity
---+-----------+-------------
1 | 1 | 10
2 | 2 | 10
3 | 1 | 10
4 | 2 | 10
5 | 1 | 10
6 | 2 | 10
I need to get the output as this one:
productId | totalPurchasedQuantity| totalSaleQuantity
----------+-----------------------+------------------
1 | 40 | 30
2 | 40 | 30
I'm using this query and how to get the desired result?
SELECT purchase_tbl.productId
, SUM(purchase_tbl.purchaseQuantity) AS totalPurchaseQuantity
, SUM(sale_tbl.saleQuantity) AS totalSaleQuantity
FROM purchase_tbl
JOIN sale_tbl
ON purchase_tbl.productId = sale_tbl.productId
GROUP BY purchase_tbl.productId
Current output
productId | totalPurchaseQuantity | totalSaleQuantity
----------+-----------------------+------------------
1 | 120 | 60
2 | 120 | 60
You better group then in separate query, as table have multiple records for each product, which getting cross product.
SELECT purchase.productId, totalPurchaseQuantity, totalSaleQuantity
FROM
(SELECT purchase_tbl.productId
, SUM(purchase_tbl.purchaseQuantity) AS totalPurchaseQuantity
FROM purchase_tbl
GROUP BY purchase_tbl.productId) purchase
INNER JOIN
(SELECT sale_tbl.productId
, SUM(sale_tbl.saleQuantity) AS totalSaleQuantity
FROM sale_tbl
GROUP BY sale_tbl.productId
) sale ON sale.productId= purchase.productId;
To obtain your expected result you have to do the aggregation on the individual table before joining them. Your query with be like:
SELECT A.productId, A.totalpurchaseQuantity, B.totalsaleQuantity
FROM
(SELECT productId, SUM(purchaseQuantity)
totalpurchaseQuantity FROM purchase_tbl
GROUP BY productId) A JOIN
(SELECT productId, SUM(saleQuantity)
totalsaleQuantity FROM sale_tbl
GROUP BY productId) B ON
A.productId=B.productId;

Check multiple columns for duplicate and list all records

I have a table with columns ID, Content and Day. I am trying to find all rows that have duplicate Content and Day values and display all rows
SELECT ID,Content, `Day`, Count(*)
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
The current code will return a list of duplicate Content and 'Day' values for instance:
ID|Content|Day
1 | a | 1
2 | a | 1
3 | a | 1
4 | b | 2
5 | b | 2
6 | c | 3
7 | c | 4
Will result in:
ID|Content|Day|Count
1 | a | 1 | 3
4 | b | 2 | 2
But I want to display all the unique IDs as well;
ID|Content|Day
1 | a | 1
2 | a | 1
3 | a | 1
4 | b | 2
5 | b | 2
Just make a Sub-Query
select *
from table
where `day` in
(
SELECT ID
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
) A
Use that query as a subquery to join against the table again:-
SELECT table.ID, table.Content, table.`Day`
FROM table
INNER JOIN
(
SELECT Content, `Day`, Count(*)
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
) sub0
ON sub0.Content = table.Content
AND sub0.`Day` = table.`Day`

Remove duplicates from one column keeping whole rows

id | userid | total_points_spent
1 | 1 | 10
2 | 2 | 15
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
With the above table, I would first like to remove duplicates of userid keeping the rows with the largest total_points_spent, like so:
id | userid | total_points_spent
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
And then I would like to sum the values of total_points_spent, which would be the easy part, resulting in 70.
I am not really sure the "remove" you meant is to delete or to select. Here is the query for select only max totalpointspend record respectively.
SELECT tblA.*
FROM ( SELECT userid, MAX(totalpointspend) AS maxtotal
FROM tblA
GROUP BY userid ) AS dt
INNER JOIN tblA
ON tblA.userid = dt.userid
AND tblA.totalpointspend = dt.maxtotal
ORDER BY tblA.userid

SQL get the products with more attributes in common with another product

I have three tables like follows:
products
id | name
1 | name1
2 | name2
3 | name3
attributes
id | name
1 | attr1
2 | attr2
3 | attr3
4 | attr4
5 | attr5
6 | attr6
7 | attr7
attr_rel Makes the relationship between prodcuts and attributes
attr_id | prod_id
1 | 1
1 | 2
2 | 1
2 | 2
3 | 3
4 | 2
4 | 3
5 | 1
5 | 2
5 | 3
What I want is to perform a query that returns all products ordered by the number of attributes they have in common with a given product.
Example: For product 3 query should return something like
id | name | num_attr_in_common
2 | product2 | 2
1 | product1 | 1
(Because product 3 shares attributes 4 and 5 with product 2 but only share attribute 5 with product 1)
Can anyone give me an help please?
select a1.prod_id,p.name,count(*) as num_attr_in_common
from attr_rel as a1
inner join (
select attr_id
from attr_rel
where prod_id = 3) as a2
on a1.attr_id = a2.attr_id and a1.prod_id <> 3
inner join products as p on p.id = a1.prod_id
group by a1.prod_id
order by num_attr_in_common desc