MySQL - Sum Table 2 Column value(s) showing all Table 1 Descriptions - mysql

I have the following tables for Transactions and Categories respectively.
I am trying to write a query that will give me results shown in the Query table below.
I have tried the following
SELECT IFNULL(categories.Name,'Total') AS category,
IFNULL(SUM( transactions.Amount),0) AS amount,
categories.Color
FROM transactions,categories
WHERE categories.CatID = transactions.CatID
GROUP BY categories.Name WITH ROLLUP
This is however not giving me Category B. I would like my Category B to be shown with a Zero - 0 total as below. Please help..
Transactions
+-----------+------------+------------+--------+
| TransID | SaleDate | CatID | Amount |
+-----------+------------+------------+--------+
| 1 | 2012-02-10 | 1 | 10 |
| 2 | 2012-02-10 | 3 | 10 |
| 3 | 2012-02-10 | 3 | 20 |
| 4 | 2012-02-10 | 1 | 25 |
| 5 | 2012-02-10 | 1 | 35 |
| 6 | 2012-02-10 | 3 | 5 |
| 7 | 2012-02-10 | 3 | 5 |
+-----------+------------+------------+--------+
Categories
+------------+------+----------+
| CatID | Name | Color |
+------------+------+----------+
| 1 | A | Green |
| 2 | B | Red |
| 3 | C | Blue |
+------------+------+----------+
GETTING RESULT BELOW
+-----------+----------------+------------+
| Category | Amount | Color |
+-----------+----------------+------------+
| A | 70 | Green |
| B | 40 | Blue |
| Total | 110 | Blue |
+-----------+----------------+------------+
#
REQUIRED RESULT
+-----------+----------------+------------+
| Category | Amount | Color |
+-----------+----------------+------------+
| A | 70 | Green |
| B | 0 | Red |
| C | 40 | Blue |
| Total | 110 | Pink |
+-----------+----------------+------------+

You are looking for a left join with rollup:
select coalesce(c.category, 'total') as category,
coalesce(sum(t.amount), 0) as amount,
coalesce(c.color, 'pink') as color -- this is weird
from categories c left join
transactions t
on c.catid = t.catid
group by c.category with rollup;

Related

Sum values based on ctiteria in MySQL

I have the following data table from which I would like to sum the values of the field 'pts' for each 'pid' as follows:
The sum of the top 3 values per 'cont' plus the values of any other 'cont' per 'pid'. The results should be presented in DESC order by 'total'
+--------+-----+------+
| pid | pts | cont |
+--------+-----+------+
| 121693 | 40 | 1 |
| 121693 | 80 | 2 |
| 121693 | 120 | 1 |
| 121693 | 100 | 1 |
| 121693 | 500 | 1 |
| 121694 | 20 | 1 |
| 121694 | 0 | 2 |
| 121694 | 30 | 3 |
| 121695 | 0 | 1 |
| 121695 | 30 | 2 |
| 121695 | 0 | 1 |
+--------+-----+------+
In this example the query should return something like this
+--------+-------+
| pid | total |
+--------+-------+
| 121693 | 800 |
| 121694 | 50 |
| 121695 | 30 |
+--------+-------+
Is this possible?
Thanks in advance.
SELECT DISTINCT pid, SUM(Pts) AS Total
FROM your tablename
GROUP BY Pid
ORDER BY TOTAL
(Requires testing and minor fixes on small syntax)

Get rows that doesn't match on another table

I have this working query that generate data the way i like it to happened but now i want it to add another clause statement that will get rows from tbl_loan_master that was not on the tbl_loanledger.
Example Data:
tbl_borrowers
------------------------------------------
| id | first_name | last_name | deleted |
| 1 | Joe | Smith | 0 |
| 2 | Lily | Mag | 0 |
| 3 | Zen | Green | 0 |
| 4 | Kim | Chan | 0 |
| 5 | Bob | Mac | 1 |
| 6 | Ben | Cork | 0 |
------------------------------------------
tbl_loan_master
----------------------------------------------------------------------
| id | borrowers_id | loan | date_created | due_date | deleted |
| 1 | 4 | 300 | 2016/04/28 | 2017/04/28 | 0 |
| 2 | 1 | 100 | 2016/05/05 | 2017/05/05 | 0 |
| 3 | 2 | 500 | 2016/06/08 | 2017/06/08 | 0 |
| 4 | 1 | 200 | 2016/06/13 | 2017/06/13 | 0 |
| 5 | 3 | 150 | 2016/06/15 | 2017/06/15 | 0 |
| 6 | 6 | 50 | 2016/06/16 | 2017/06/16 | 0 |
----------------------------------------------------------------------
tbl_loanledger
------------------------------------------------------------------------------
| id | borrowers_id | loanmaster_id | payment | balance| date_created | deleted
| 1 | 4 | 1 | 50 | 250 | 2016/05/28 | 0
| 2 | 1 | 2 | 20 | 80 | 2016/05/25 | 0
| 3 | 1 | 2 | 30 | 50 | 2016/06/01 | 0
| 4 | 2 | 3 | 100 | 400 | 2016/06/09 | 0
| 5 | 2 | 3 | 50 | 350 | 2016/06/10 | 0
| 6 | 3 | 4 | 50 | 150 | 2016/06/16 | 0
------------------------------------------------------------------------------
Here is the working query:
$query = "SELECT `tbl_borrowers`.* , `tbl_loanledger`.*, `tbl_loan_master`.*
FROM `tbl_borrowers`
LEFT JOIN `tbl_loanledger`
ON `tbl_borrowers`.id = `tbl_loanledger`.borrower_id
LEFT JOIN `tbl_loan_master`
ON `tbl_loan_master`.id = `tbl_loanledger`.loanmaster_id
WHERE `tbl_borrowers`.deleted = 0 AND `tbl_loanledger`.deleted = 0 AND MONTH ( `tbl_loanledger`.date_created) = MONTH(CURRENT_DATE)
GROUP BY `tbl_loanledger`.borrower_id
ORDER BY `tbl_borrowers`.last_name";
The expected result will output the borrowers with their last transaction on the current month (which is June) in loan ledger and also in loans accounts. Like Ben Cork which is not on the loan ledger, he is on the loan accounts but i want to output him on the result set. The deleted column means if it is 0 it indicates it is active if it is 0 it means it has been deleted.
Expected Result:
|First Name | Last Name | Due Date | Balance |
| Ben | Cork | 2017/06/16 | 50 |
| Joe | Smith | 2017/06/13 | 50 |
| Lily | Mag | 2017/06/08 | 350 |
| Zen | Green | 2017/06/15 | 150 |
Try following;)
select
tb.first_name, tb.last_name, coalesce(tlm.Loan, 0) as Loan, coalesce(t.`Amount Paid`, 0) as `Last Amount Paid`
from tbl_borrowers tb
left join tbl_loan_master tlm
on tb.id = tlm.borrowers_id
left join (
select t1.*
from tbl_loanledger t1
inner join (
select max(id) as id
from tbl_loanledger
group by borrowers_id, loanmaster_id
) t2 on t1.id = t2.id
) t
on tb.id = t.borrowers_id
and tlm.id = t.loanmaster_id
SQLFiddle DEMO HERE

MySQL, ordering GROUP BY

I have a table that has some values in it, along with the time that value was taken against an associated ID from another table.
I am looking to retrieve the latest value for every item in that table, and then order by those latest values.
Here is an SQL fiddle, http://www.sqlfiddle.com/#!2/0be99
And here is text output.
'hist' table
| HIST_ID | HIST_ITEM_ID | HIST_VALUE | HIST_TIME |
|---------|--------------|------------|------------|
| 1 | 1 | 1 | 1420291000 |
| 2 | 1 | 2 | 1420292000 |
| 3 | 1 | 3 | 1420293000 |
| 4 | 1 | 5 | 1420294000 |
| 5 | 1 | 10 | 1420295000 |
| 6 | 1 | 50 | 1420296000 |
| 7 | 1 | 60 | 1420297000 |
| 8 | 1 | 77 | 1420298000 |
| 9 | 1 | 90 | 1420299000 |
| 10 | 1 | 101 | 1420300000 |
| 11 | 2 | 1 | 1420291000 |
| 12 | 2 | 3 | 1420292000 |
| 13 | 2 | 7 | 1420293000 |
| 14 | 2 | 9 | 1420294000 |
| 15 | 2 | 15 | 1420295000 |
| 16 | 2 | 21 | 1420296000 |
| 17 | 2 | 33 | 1420297000 |
| 18 | 2 | 35 | 1420298000 |
| 19 | 2 | 55 | 1420299000 |
| 20 | 2 | 91 | 1420300000 |
'items' table
| ITEM_ID | ITEM_TITLE |
|---------|------------|
| 1 | ABCD |
| 2 | XYZ123 |
So, I can do something like...
select * from hist
inner join items on hist_item_id = item_id
group by hist_item_id
order by hist_value desc
However this returns me a grouping that I cannot order. How can I order this grouping? I had a look at other similar questions on here but was unable to apply their solutions successfully to my query to produce the desire result.
The desired result here would be to return.
HIST_ITEM_ID | ITEM_TITLE | HIST_VALUE |
|------------|------------|------------|
| 1 | ABCD | 101 |
| 2 | XYZ123 | 91 |
You can use a join to get the most recent history item. Then you can join back to the history table and the item table to get additional information:
select h.*, i.item_title
from (select hist_item_id, max(hist_id) as max_hist_id
from hist
group by hist_item_id
) hh join
hist h
on h.hist_id = hh.max_hist_id join
items i
on i.item_id = hh.hist_item_id;
Here is a SQL Fiddle.
You should use MAX function and group by the item id. That would look like this:
SELECT i.item_id, i.item_title, MAX(h.hist_value)
FROM items AS i
INNER JOIN hist AS h
ON i.item_id = h.hist_item_id
GROUP BY i.item_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..

Calculate percentage for an area of study

I need help for generating a SQL for MySQL database.
I have two tables:
Students
student_Subjects
Students table:
+------------+---------+-----------------+
| id | name |area_of_study_id |
+------------+---------+-----------------+
| 1 | AAA | 1 |
| 2 | BBB | 2 |
| 3 | CCC | 1 |
| 4 | DDD | 3 |
| 5 | EEE | 4 |
| 6 | FFF | 1 |
| 7 | GGG | 2 |
| 8 | III | 1 |
+------------+---------+-----------------+
student_subjects table:
+------------+-------------------+------------------+
| id | student_id | subject_id |
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 3 |
| 4 | 1 | 2 |
| 5 | 3 | 1 |
| 6 | 6 | 1 |
| 7 | 7 | 3 |
| 8 | 4 | 6 |
+------------+-------------------+------------------+
I need to find out a subject's area of study based on students area of study. From above students table you can see that students have the freedom to choose the area of study. Sometimes, they can choose subjects which are not related to their area of study. So, in this case, we need to calculate area of study for a subject based on the student percentages who have taken the subjects.
Partial output:
+------------+-------------------+-----------------------------------+
|Total_students | subject_id |area_of_study_id | percentage |
+------------+-------------------+-----------------+-----------------+
| 3 | 1 | 1 | 75 |
| 1 | 1 | 2 | 25 |
| 1 | 3 | 1 | 50 |
| 1 | 3 | 2 | 50 |
| 1 | 2 | 1 | 100 |
| 1 | 6 | 3 | 100 |
+------------+-------------------+-----------------+-----------------+
From above partial output, we can see, 3 students choose a subject(i.e subject_id =1) have the area of study 1 and one student is from different area of study (i.e 2). So, we can say subject_id =1 is from area of study = 1.
if percentage 50% for a subject. we can choose any area of study between two, no matter which one.
Expected output:
+------------+-------------------+-----------------------------------+
|Total_students | subject_id |area_of_study_id | percentage |
+------------+-------------------+-----------------+-----------------+
| 3 | 1 | 1 | 75 |
| 1 | 3 | 1 | 50 |
| 1 | 2 | 1 | 100 |
| 1 | 6 | 3 | 100 |
+------------+-------------------+-----------------+-----------------+
Try it this way
SELECT subject_id, area_of_study_id, total_students, percentage
FROM
(
SELECT p.subject_id, p.area_of_study_id, p.total_students,
p.total_students / t.total_students * 100 percentage
FROM
(
SELECT COUNT(*) total_students, ss.subject_id, s.area_of_study_id
FROM students s JOIN student_subjects ss
ON s.id = ss.student_id
GROUP BY ss.subject_id, s.area_of_study_id
) p JOIN
(
SELECT ss.subject_id, COUNT(*) total_students
FROM students s JOIN student_subjects ss
ON s.id = ss.student_id
GROUP BY ss.subject_id
) t ON p.subject_id = t.subject_id
ORDER BY percentage DESC
) q
GROUP BY subject_id;
Output:
| SUBJECT_ID | AREA_OF_STUDY_ID | TOTAL_STUDENTS | PERCENTAGE |
|------------|------------------|----------------|------------|
| 1 | 1 | 3 | 75 |
| 2 | 1 | 1 | 100 |
| 3 | 1 | 1 | 50 |
| 6 | 3 | 1 | 100 |
Here is SQLFiddle demo