SUM of Column where Multiple Rows Have Same Value - mysql

I am trying to get the sum of a single column from all rows that share similar data. For example, given the following data:
|ppID | cID | Count | NameSpace|
|-----|-------|-------|----------|
|586 | 18281 | 1 | LAB |
|587 | 18269 | 1 | LAB |
|588 | 18281 | 1 | LAB |
|589 | 17823 | 1 | IPB |
|590 | 18281 | 1 | LAB |
|591 | 18256 | 1 | LAB |
|592 | 18256 | 1 | LAB |
|593 | 18269 | 1 | IPB |
|-----|-------|-------|----------|
I'm hoping to get:
|ppID | cID | Count | NameSpace|
|-----|-------|-------|----------|
|586 | 18281 | 3 | LAB |
|587 | 18269 | 1 | LAB |
|589 | 17823 | 1 | IPB |
|591 | 18256 | 2 | LAB |
|593 | 18269 | 1 | IPB |
|-----|-------|-------|----------|
I've pieced together a couple of different things and come up with `
SELECT * FROM PopularPages
WHERE cID IN (SELECT cID FROM PopularPages
GROUP BY cID
HAVING COUNT(cID) > 1)
ORDER BY cID, Namespace
which will list out each of the rows but without counting up the sum of the Count column. Any help would be appreciated.

is this what you want ?
SELECT
MIN(ppID) as ppID,
cID,
SUM(`Count`) as COUNT,
NameSpace
FROM PopularPages
GROUP BY cID
HAVING Count > 1;

Related

MySql get Count, Value from 3rd Table with reference from 1st table

i would like to get the Count value from the 3rd table... 1st table has reference id to 2nd table, 2nd table has reference id of 3rd table... in 3rd table has the value... that i need to count...
Table struct:
table1: tbl_rack
+------------+---------+--------+
| rack_id | site_id | status |
+------------+---------+--------+
| R-642 | ST5 | Y |
| R-307 | ST6 | Y |
| R-57 | ST7 | Y |
| 390/6 | ST8 | Y |
| 9706 | ST11 | Y |
table2: tbl_site
+---------+-------------+-----------+
| site_id | customer_id | region_id |
+---------+-------------+-----------+
| ST5 | CM8 | RM4 |
| ST6 | CM8 | RM8 |
| ST7 | CM10 | RM2 |
| ST8 | CM11 | RM12 |
| ST11 | CM8 | RM10 |
table3: tbl_customer
+-------------+----------------------+---------------+
| customer_id | customer_name | customer_type |
+-------------+----------------------+---------------+
| CM8 | LIVI-IN | MODERATE |
| CM10 | PEPE | HIGH |
| CM11 | SANDER | LOW |
| CM12 | TOASTER | MODERATE |
I want to count each customers contains how many Racks where ranks status is 'Y'
expected Result1:
Customer No.of Racks
LIVI-IN 3
OTHERS 2
expected Result2:
Customer Type No.of Racks
Moderate 3
High 1
Low 1
Please, follow below SQL query:
select C.customer_name as 'Customer', count(*) as 'No.of Racks'
from tbl_customer C
left outer join tbl_site TS on TS.customer_id = C.customer_id
left outer join tbl_rack TR on TR.site_id = TS.site_id
group by C.customer_name
order by C.customer_name

mysql pivot using column and row numbers

I am stuck in this situation where I need to use Row Number and Column Number values from table's columns to derive the output mentioned below. I have tried everything - if/else, case when/then but not helping.
Any help/suggestions are really appreciated!
Here is a mocked up sample data present in db table -
+--------+--------+--------+----------+-------------+
| Record | ColNbr | RowNbr | ColTitle | CellContent |
+--------+--------+--------+----------+-------------+
| 1 | 1 | 1 | Unit | sqf |
| 1 | 1 | 2 | Unit | cm |
| 1 | 2 | 1 | Desc | roof |
| 1 | 2 | 2 | Desc | rod |
| 1 | 3 | 1 | Material | concrete |
| 1 | 3 | 2 | Material | steel |
| 1 | 4 | 1 | Quantity | 100 |
| 1 | 4 | 2 | Quantity | 12 |
| 1 | 1 | 1 | Unit | liter |
| 1 | 1 | 2 | Unit | ml |
| 1 | 2 | 1 | Desc | bowl |
| 1 | 2 | 2 | Desc | plate |
| 1 | 3 | 1 | Material | plastic |
| 1 | 3 | 2 | Material | glass |
| 1 | 4 | 1 | Quantity | 2 |
| 1 | 4 | 2 | Quantity | 250 |
+--------+--------+--------+----------+-------------+
Expected Output -
+--------+--------+--------+----------+-------------+
| Record | Unit | Desc | Material | Quantity |
+--------+--------+--------+----------+-------------+
| 1 | sqf | roof | concrete | 100 |
| 1 | cm | rod | steel | 12 |
| 2 | liter | bowl | plastic | 2 |
| 2 | ml | plate | glass | 250 |
+--------+--------+--------+----------+-------------+
If your actual data is like that, I suggest that you consider to separate the data to; for example, 4 different tables (unit,description,material & a table to store all that ids+quantity). The former 3 tables will store the prerequisite info that get minor updates throughout time and the last table will store all the quantity records. Let's say your tables will look something like this:
CREATE TABLE `Unit` (
unit_id INT,
unit_name VARCHAR(50));
+---------+-----------+
| unit_id | unit_name |
+---------+-----------+
| 1 | sqf |
| 2 | cm |
| 3 | liter |
| 4 | ml |
+---------+-----------+
CREATE TABLE `Description` (
desc_id INT,
desc_name VARCHAR(50));
+---------+-----------+
| desc_id | desc_name |
+---------+-----------+
| 1 | roof |
| 2 | rod |
| 3 | bowl |
| 4 | plate |
+---------+-----------+
CREATE TABLE `Material` (
mat_id INT,
mat_name VARCHAR(50));
+--------+----------+
| mat_id | mat_name |
+--------+----------+
| 1 | concrete |
| 2 | steel |
| 3 | plastic |
| 4 | glass |
+--------+----------+
CREATE TABLE `Records` (
unit_id INT,
desc_id INT,
mat_id INT,
quantity DECIMAL(14,4));
+---------+---------+--------+----------+
| unit_id | desc_id | mat_id | Quantity |
+---------+---------+--------+----------+
| 1 | 1 | 1 | 100 |
| 2 | 2 | 2 | 12 |
| 3 | 3 | 3 | 2 |
| 4 | 4 | 4 | 250 |
+---------+---------+--------+----------+
Then you insert the data accordingly.
Anyhow, for your existing data example, it could be done but there are some concern over whether the unit+desc+material+quantity matching are correct. The only way I can maybe at least think that it's correctly matched is by giving all of the query a similar ORDER BY clause. Hence, the following:
SELECT A.record,A.unit,B.Desc,C.Material,D.Quantity FROM
(SELECT #rn:=#rn+1 AS record,CASE WHEN coltitle='unit' THEN cellcontent END AS Unit
FROM yourtable, (SELECT #rn :=0 ) v
HAVING unit IS NOT NULL
ORDER BY colnbr) A LEFT JOIN
(SELECT #rn1:=#rn1+1 AS record,CASE WHEN coltitle='Desc' THEN cellcontent END AS `Desc`
FROM yourtable, (SELECT #rn1 :=0 ) v
HAVING `Desc` IS NOT NULL
ORDER BY colnbr) B ON a.record=b.record LEFT JOIN
(SELECT #rn2:=#rn2+1 AS record,CASE WHEN coltitle='material' THEN cellcontent END AS Material
FROM yourtable, (SELECT #rn2:=0 ) v
HAVING Material IS NOT NULL
ORDER BY colnbr) C ON a.record=c.record LEFT JOIN
(SELECT #rn3:=#rn3+1 AS record,CASE WHEN coltitle='Quantity' THEN cellcontent END AS Quantity
FROM yourtable, (SELECT #rn3:=0 ) v
HAVING Quantity IS NOT NULL
ORDER BY colnbr) D ON a.record=d.record;
The idea here is to make a sub-query based on COLTITLE then assign a numbering/ranking (#rn,#rn1,#rn2,#rn3) variable to each of the sub-query and join them up using LEFT JOIN. Now, this experiment works to exactly return the output that you need but its not a definite answer because there are some part that is questionable especially on matching the combination correctly. Hopefully, this will give you some idea.

How to ROLLUP a SUM over multiple columns on separate tables?

I have 4 tables from which I want to aggregate data using MySQL 5.7.
Projects
+------------+--------+------------------+
| project_id | org_id | name |
+------------+--------+------------------+
| 1 | 1 | Big Project |
| 2 | 1 | Internal Project |
+------------+--------+------------------+
Tasks
+-----------+--------+----------------+------------+
| task_id | org_id | name | project_id |
+-----------+--------+----------------+------------+
| 1 | 1 | Check Work | 1 |
| 2 | 1 | Fix Code | 1 |
| 3 | 1 | Rebuild Office | 2 |
+-----------+--------+----------------+------------+
Resources
+-------------+--------+-------------+-----------+
| resource_id | org_id | first_name | last_name |
+-------------+--------+-------------+-----------+
| 1 | 1 | Alice | Black |
| 2 | 1 | Bob | Smith |
| 3 | 1 | Charlie | White |
+-------------+--------+-------------+-----------+
Task_Details
+-------------+--------+---------+-------------+
| resource_id | org_id | task_id | total_hours |
+-------------+--------+---------+-------------+
| 1 | 1 | 1 | 12 |
| 2 | 1 | 1 | 4 |
| 3 | 1 | 1 | 8 |
| 2 | 1 | 2 | 4 |
| 3 | 1 | 2 | 4 |
| 1 | 1 | 3 | 16 |
+-------------+--------+---------+-------------+
I want to SUM the total_hours, GROUPing by task and project, while still showing the total_hours each employee has individually spent on a task. The output I'm looking for would be something like this
Desired Output
+------------------+----------------+------------+-----------+-------------+
| project_name | task_name | first_name | last_name | total_hours |
+------------------+----------------+------------+-----------+-------------+
| Big Project | Check Work | Alice | Green | 12 |
| Big Project | Check Work | Bob | Smith | 4 |
| Big Project | Check Work | Charlie | Brown | 8 |
| Big Project | Check Work | NULL | NULL | 24 |
| Big Project | Fix Code | Bob | Smith | 4 |
| Big Project | Fix Code | Charlie | Brown | 4 |
| Big Project | Fix Code | NULL | NULL | 8 |
| Big Project | NULL | NULL | NULL | 32 |
| Internal Project | Rebuild Office | Alice | Green | 16 |
| Internal Project | Rebuild Office | NULL | NULL | 16 |
| Internal Project | NULL | NULL | NULL | 16 |
+------------------+----------------+------------+-----------+-------------+
I've managed to create a query that JOINs the relevant tables together, and even managed to GROUP them by project_id, task_id and resource_id. However, adding a WITH ROLLUP statement to the end of my query causes it to fail even though it works without one.
This is my current query:
SELECT
t1.project_name,
t1.task_name,
t2.first_name,
t2.last_name,
SUM(t1.task_hours)
FROM (
SELECT
Projects.project_id,
Projects.name AS project_name,
Tasks.task_id,
Tasks.name AS task_name,
Resources.resource_id,
Task_Details.total_hours AS task_hours
FROM
Projects
RIGHT OUTER JOIN
Tasks
ON
Projects.org_id = Tasks.org_id AND
Projects.project_id = Tasks.project_id
LEFT OUTER JOIN
Task_Details
ON
Task_Details.org_id = Tasks.org_id AND
Task_Details.task_id = Tasks.task_id
LEFT OUTER JOIN
Resources
ON
Resources.org_id = Task_Details.org_id AND
Resources.resource_id = Task_Details.resource_id
WHERE
Projects.org_id = 1
) AS t1
JOIN (
SELECT
resource_id,
first_name,
last_name
FROM
Resources
WHERE
org_id = 1
) AS t2
ON
t2.resource_id = t1.resource_id
GROUP BY
t1.project_id,
t1.task_id,
t1.resource_id;
How can I modify my query such that WITH ROLLUP works?
My SQLFiddle is here, but notably is for MySQL 5.6 rather than 5.7
IMHO, the problem with your query is this: You select some columns which are not in the GROUP BY. That causes some non-sensical values in the columns first_name, last_name, project_name and task_name. However, the sum column is probably correct, isn't it?
This works for me:
SELECT p.name as project_name,
s1.task_name,
first_name,
last_name,
s1.total_hours
FROM (
SELECT
t.project_id,
t.name as task_name,
h.resource_id,
sum(h.total_hours) as total_hours
FROM Task_Details as h
JOIN Tasks as t ON (t.task_id=h.task_id)
GROUP BY t.project_id, t.name, h.resource_id WITH ROLLUP
) AS s1
LEFT JOIN Resources AS r ON (s1.resource_id=r.resource_id)
JOIN Projects AS p ON (p.project_id=s1.project_id);
The nested SELECT does the interesting work, it sums up the total_hours of every resource_id, every task_name and and every project_id. The nesting SELECT then collects the name of every resource and project.
OUTPUT:
+------------------+----------------+------------+-----------+-------------+
| project_name | task_name | first_name | last_name | total_hours |
+------------------+----------------+------------+-----------+-------------+
| Big Project | NULL | NULL | NULL | 32 |
| Big Project | Check Work | Alice | Green | 12 |
| Big Project | Check Work | NULL | NULL | 24 |
| Big Project | Check Work | Bob | Smith | 4 |
| Big Project | Check Work | Charlie | Brown | 8 |
| Big Project | Fix Code | Bob | Smith | 4 |
| Big Project | Fix Code | Charlie | Brown | 4 |
| Big Project | Fix Code | NULL | NULL | 8 |
| Internal Project | NULL | NULL | NULL | 16 |
| Internal Project | Rebuild Office | NULL | NULL | 16 |
| Internal Project | Rebuild Office | Alice | Green | 16 |
+------------------+----------------+------------+-----------+-------------+
Hope this helps.

MySQL Limit Results Based on Join Table

I have 2 tables,but linked in many to many relations so 3 tables :
Table Author :
idAuthor,
Name
+----------+-------+
| idAuthor | Name |
+----------+-------+
| 1 | Renee |
| 2 | John |
| 3 | Bob |
| 4 | Bryan |
+----------+-------+
Table Publication:
idPublication,
Title,
Type,
Date,
Journal,
Conference
+---------------+--------------+------+-------------+------------+-----------+
| idPublication | Title | Date | Type | Conference | Journal |
+---------------+--------------+------+-------------+------------+-----------+
| 1 | Flower thing | 2008 | book | NULL | NULL |
| 2 | Bees | 2009 | article | NULL | Le Monde |
| 3 | Wasps | 2010 | inproceding | KDD | NULL |
| 4 | Whales | 2010 | inproceding | DPC | NULL |
| 5 | Lyon | 2011 | article | NULL | Le Figaro |
| 6 | Plants | 2012 | book | NULL | NULL |
+---------------+--------------+------+-------------+------------+-----------+
Table author_has_publication :
Author_idAuthor,
Publication_idPublication
+-----------------+---------------------------+
| Author_idAuthor | Publication_idPublication |
+-----------------+---------------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 3 | 6 |
+-----------------+---------------------------+
What I want to do is get the top X author having the most publications.
I achieved to get the result avec the idAuthor having the most publications, using this request :
SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC;
I get the list of the authors id, ordered by the number of publications :
+-----------------+-------+
| Author_idAuthor | count |
+-----------------+-------+
| 3 | 3 |
| 2 | 2 |
| 1 | 2 |
| 4 | 1 |
+-----------------+-------+
but then when I try to select the author corresponding to the top X of the result set of the previous query I have an error
I am Trying this SELECT TOP 2 FROM author WHERE (SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC)=idAuthor;
I think it might be because my inside query return 2 rows, and I do a simple SELECT here or that I need a JOIN but i have no ideas how to use it here.
MySQL has no TOP keyword. It does however have a LIMIT keyword. Your query is invalid anyway.
There are a couple of options here. The following is an example of a correlated subquery: https://en.wikipedia.org/wiki/Correlated_subquery
SELECT
a.idAuthor,
a.Name ,
(SELECT COUNT(*) from author_has_publication ahp WHERE
ahp.Author_idAuthor = a.idAuthor) AS publication_count
FROM
author a
ORDER BY
publication_count DESC
LIMIT 2
As the referenced article notes, the above is inefficient as the subquery needs to be re-executed for each row of the result. If you do not actually need the count in the resultset then the below would be more efficient as the subquery is non-correlated and executed only once.
SELECT
a.idAuthor,
a.Name
FROM
author a
INNER JOIN
(select ahp.Author_idAuthor AS idAuthor, COUNT(*) as publication_count
FROM author_has_publication ahp GROUP BY ahp.Author_idAuthor LIMIT 2)
AS TEMP ON TEMP.idAuthor = a.idAuthor

COUNT reducing results?

A query without COUNT returns 3 records, with only 1.
SELECT `blog_cate` . * , COUNT( blogi.blog_cate ) AS num
FROM (
`blog_cate`
)
JOIN `blogi` ON `blogi`.`blog_cate` = `blog_cate`.`blogi_cate_url`
results:
+----+------------------+----------------+-----+
| id | blogi_cate_title | blogi_cate_url | num |
+----+------------------+----------------+-----+
| 1 | Базы данных | batabase | 3 |
+----+------------------+----------------+-----+
And the same query, but without a COUNT:
SELECT `blog_cate` . *
FROM (
`blog_cate`
)
JOIN `blogi` ON `blogi`.`blog_cate` = `blog_cate`.`blogi_cate_url`
That returns me 3 records:
+----+------------------+----------------+
| id | blogi_cate_title | blogi_cate_url |
+----+------------------+----------------+
| 1 | Базы данных | batabase |
| 1 | Базы данных | batabase |
| 3 | Разработка | razrabotka |
+----+------------------+----------------+
Is it possible to use a COUNT and have a normal results?
p.s. tables:
+----+------------+
| id | blog_cate |
+----+------------+
| 1 | batabase |
| 2 | batabase |
| 3 | razrabotka |
+----+------------+
+----+------------------+----------------+
| id | blogi_cate_title | blogi_cate_url |
+----+------------------+----------------+
| 1 | Базы данных | batabase |
| 2 | PHP | php |
| 3 | Разработка | razrabotka |
+----+------------------+----------------+
COUNT() with out a group by will group all records and produce a count of them. Adding more fields to the select will only show the details of the first record
You could build one query to get the three rows and one query to get the count result and join them via cross join to combine every detail row with the count row.