MySQL Summing & Counting Child Values in Another Table - mysql

BOOKINGS TABLE
id | price | anotherVal
-----------------------------
1 | 10000 | *
2 | 20000 | *
3 | 1000 | *
4 | 8000 | *
BOOKING PAYMENTS TABLE
id | bookingId | amount | currencyId | mxnAmount
--------------------------------------------------
1 | 1 | 100.00 | 1 | 100.00
2 | 1 | 300.00 | 3 | 6400.00
3 | 2 | 500.21 | 1 | 500.21
4 | 4 | 123.95 | 6 |
4 | 4 | 800.00 | 1 | 800.00
I need to get all BOOKINGS_TABLE columns and then for each booking add up the mxnAmount column, but also the result should tell if all rows in BOOKING_PAYMENTS_TABLE had an mxnAmount so i can know if the mxnAmount is final or there's some rows left to be updated, i have a query that works for the first part:
SELECT b.*, SUM(p.mxnAmount) FROM bookings b LEFT JOIN bookingPayments p ON b.id = p.bookingId GROUP BY b.id
I figured i could make us of COUNT() to count all rows in BOOKING_PAYMENTS_TABLE but then how can i get the number for the rows that have an mxnAMOUNT?
SELECT b.*, SUM(p.mxnAmount), COUNT(p.id) FROM bookings b LEFT JOIN bookingPayments p ON b.id = p.bookingId GROUP BY b.id
I tried this:
SELECT b.*, SUM(p.mxnAmount), COUNT(p.id), COUNT(pp.id) FROM bookings b LEFT JOIN bookingPayments p ON b.id = p.bookingId LEFT JOIN bookingPayments pp ON b.id = pp.bookingId WHERE pp.mxnAmount IS NOT NULL GROUP BY b.id
But then the query returns only bookings that have all their payments rows with an mxnAmount, any leads?

I figured i could make us of COUNT() to count all rows in BOOKING_PAYMENTS_TABLE but then how can i get the number for the rows that have an mxnAMOUNT?
Just COUNT() that particular column: this gives you the number of non-null values in the column for each group:
SELECT b.*, SUM(p.mxnAmount), COUNT(p.id), COUNT(p.mxnAmount)
FROM bookings b
LEFT JOIN bookingPayments p ON b.id = p.bookingId
GROUP BY b.id
If you want to know if any mxmamount in the group is missing, you can do:
MAX(p.id IS NOT NULL AND p.mxnAmount IS NULL) has_missing_mxnAmount

Related

How to count in mysql

I have this query in mySQL where I would like to sum the line product of each doctor but I dont know how to do it.
use avant_medical;
select
sales.doctor_id as DoctorID,
line_products.id as LineProductID,
line_products.name as LineProductName
from `doctors`
inner join `sales` on `doctors`.`id` = `sales`.`doctor_id`
inner join `inventories` on `sales`.`id` = `inventories`.`sale_id`
inner join `products` on `inventories`.`product_id` = `products`.`id`
inner join `line_products` on `products`.`lineProduct_id` = `line_products`.`id`
order by `doctors`.`id` asc;
lPID= lineProductID
|DrID|lPID |
| -- | ----|
| 1 | 7 |
| 1 | 6 |
| 1 | 6 |
| 1 | 7 |
| 1 | 7 |
| 1 | 7 |
| 1 | 6 |
This is how I want:
Doctor 1
lineID | quantity
7 | 4
6 | 3
I try this query only in mySQL
The keyword you are looking for is count, not sum. Summing would add up every lineProductID as if they where regular mathematical values, while counting will add up how many times a given lineProductID is found.
select
sales.doctor_id as DoctorID,
line_products.id as LineProductID,
line_products.name as LineProductName,
-- We count the number of occurrences of each line_product.id
COUNT(line_products.id) as LineProductQty
from `doctors`
inner join `sales` on `doctors`.`id` = `sales`.`doctor_id`
inner join `inventories` on `sales`.`id` = `inventories`.`sale_id`
inner join `products` on `inventories`.`product_id` = `products`.`id`
inner join `line_products` on `products`.`lineProduct_id` = `line_products`.`id`
-- Never forget to properly GROUP your aggregate functions, such as COUNT() or SUM()!
GROUP BY sales.doctor_id, line_products.id, line_products.name
order by `doctors`.`id` asc;
Since you didn't provided full schema to test this, I made a small, very artificial demo, but should be representative of how the query above works.

Select * as well as count/sum from another table

I am trying to write a MySQL query to select all rows from table a, as well as information from table b, while also querying the count and sum of values in another table c, for each row of a.
I will try to break that down a bit better, here is a simplified version of my tables:
Table A
+---------+----------+-----------+
| id | name | bid |
+---------+----------+-----------+
| 1 | abc | 1 |
| 2 | def | 1 |
| 3 | ghi | 2 |
+--------------------------------+
Table B
+---------+----------+
| id | name |
+---------+----------+
| 1 | STAN |
| 2 | UCLA |
+--------------------+
Table C
+---------+----------+-----------+
| id | aid | cnumber |
+---------+----------+-----------+
| 1 | 1 | 40 |
| 2 | 1 | 20 |
| 3 | 2 | 10 |
| 4 | 3 | 40 |
| 5 | 3 | 20 |
| 6 | 3 | 10 |
+--------------------------------+
What I need is a query that will return rows containing
a.id | a.name | b.id | b.name | SUM(c.cnumber) | COUNT(c.cnumber)
I am not sure if such a thing is even possible in MySQL.
My current solution is trying to query A + B Left Join and then UNION with A + C Right Join. It's not giving me the results I'm looking for however.
Thanks.
edit:
current query re-written for this problem:
SELECT
a.id,
a.name,
b.id,
b.name
"somecolumn" as dummy_column
"somecolumn1" as dummy_column1
FROM a
LEFT OUTER JOIN b ON a.b.id = b.id
UNION
SELECT
"somecolumn" as dummy_column
"somecolumn1" as dummy_column1
"somecolumn2" as dummy_column2
"somecolumn3" as dummy_column3
COUNT(c.cnumber) AS ccount
SUM(c.cnumber) AS sum
FROM a
RIGHT OUTER JOIN c ON a.id = c.a.id;
Unfortunately MySQL doesn't have FULL OUTER JOIN, and this is my temporary work around, although I don't think it's even the proper idea.
My desired output is all the rows from table A with some info from table B, as well as their totaled inputs in table C.
edit2:
SELECT
a.id,
a.name,
b.id,
SUM(c.cnumber) as totalSum,
(SELECT count(*) FROM c as cc WHERE cc.aid = a.id) as totalCount
FROM
a
LEFT JOIN b ON a.bid = b.id
LEFT JOIN c ON c.aid = a.id;
For future similar questions, solution:
SELECT
a.id AS aid,
a.name,
b.id,
(SELECT SUM(c.rating) FROM c WHERE c.aid = aid) AS totalSum,
(SELECT COUNT(c.rating) FROM c WHERE c.aid = aid) AS totalCount
FROM
a
LEFT JOIN b ON a.bid = b.id;
Your query should be :-
SELECT
a.id,
a.name,
b.id,
(SELECT SUM(c.cnumber) FROM c as cd WHERE cd.aid = a.id) as totalSum,
(SELECT count(*) FROM c as cc WHERE cc.aid = a.id) as totalCount
FROM
a
LEFT JOIN b ON a.bid = b.id
LEFT JOIN c ON c.aid = a.id;
It may help you.
I have tried your example.
SELECT * ,
(SELECT SUM(cnumber) FROM `table_c` WHERE `table_c`.`iaid` = `table_a`.`id`),
(SELECT COUNT(cnumber) FROM `table_c` WHERE `table_c`.`a.id` = `table_a`.`id`)
FROM `table_a`,`table_b` WHERE `table_b`.`id` = `table_a`.`b.id`
i got the Following output.

Sum columns from multiple tables in MySQL

I am trying to sum some columns from multiple tables in just one SQL query, but I seem to be getting the wrong results. I think there is a problem with the code that I have provided below. Please any help on this is appreciated.
item Names
| id | name |
| 1 | AB |
| 2 | CA |
table1
| id | interest | year |
| 1 | 20.00 | 2014 |
| 2 | 30.00 | 2013 |
| 1 | 10.00 | 2013 |
table2
| id | deposit | year |
| 1 | 10.00 | 2014 |
| 2 | 10.00 | 2014 |
This is the query that I tried:
SELECT
a.name,
b.year,
sum(b.interest) as 'total'
FROM
`table1` b
INNER JOIN
`item names` a
ON
b.id=a.id
GROUP BY
b.id
UNION ALL
SELECT
c.name,
d.year,
sum(d.deposit) as 'total'
FROM
`table2` d
INNER JOIN
`item names` c
ON
d.id=c.id
GROUP BY
d.id
EXPECTED RESULTS
UPDATE
I am trying to find the total sum of interest and deposit for a particular year and for a particular item
|name | year | total |
| AB | 2014 | 30.00 |
| AB | 2013 | 10.00 |
| CA | 2013 | 30.00 |
| CA | 2014 | 10.00 |
Perhaps... assuming table1 and table2 have same structure.
First I generate a set with the union values from one and two then we use a simple aggregate and a group by to sum the values by name and year.
SELECT I.Name, B.year, Sum(B.Total)
FROM item I
INNER JOIN
(SELECT * FROM table1 UNION select * FROM table2) B
on B.ID = I.ID
GROUP BY I.Name, B.Year
In the query you have posted, you need to group by year also to get the results. Then, you can use UNION to get all of the rows from the first set, along with all of the rows from the second set:
SELECT a.name, b.year, SUM(b.interest) AS total
FROM names a
JOIN table1 b ON b.id = a.id
GROUP BY a.name, b.year
UNION
SELECT a.name, c.year, SUM(c.deposit) AS total
FROM names a
JOIN table2 c ON c.id = a.id
GROUP BY a.name, c.year;
However, this doesn't give you your final results, as names that appear in each table ('AB' for example) will appear twice. One row for the year in deposits, one row for the year in interests. To combine those, just use the above as a subquery, sum the totals and again group by name and date:
SELECT name, year, SUM(total) AS total
FROM(
SELECT a.name, b.year, SUM(b.interest) AS total
FROM names a
JOIN table1 b ON b.id = a.id
GROUP BY a.name, b.year
UNION
SELECT a.name, c.year, SUM(c.deposit) AS total
FROM names a
JOIN table2 c ON c.id = a.id
GROUP BY a.name, c.year) temp
GROUP BY name, year;
Here is an SQL Fiddle example.

Select data from another table if exists, if not display null

I have two tables.
Invoices
ID | Amount
-----------
1 | 123.54
2 | 553.46
3 | 431.34
4 | 321.31
5 | 983.12
Credit Memos
ID | invoice_ID | Amount
------------------------
1 | 3 | 25.50
2 | 95 | 65.69
3 | 51 | 42.50
I want to get a result set like this out of those two tables
ID | Amount | Cr_memo
---------------------
1 | 123.54 |
2 | 553.46 |
3 | 431.34 | 25.50
4 | 321.31 |
5 | 983.12 |
I've been messing with joins and whatnot all morning with no real luck.
Here is the last query I tried, which pulled everything from the Credit Memo table...
SELECT A.ID, A.Amount FROM Invoices AS A
LEFT JOIN Credit_Memos AS B ON A.ID = B.invoice_ID
Any help or pointers are appreciated.
Your query would work fine. Just add Credit_memo.Amount with an alias:
SELECT Inv.ID,Inv.Amount,IFNULL(C.Amount,'') AS Cr_memo
FROM Invoices Inv LEFT JOIN
Credit_Memos C ON Inv.ID=C.invoice_ID
Result:
ID AMOUNT CR_MEMO
1 124
2 553
3 431 25.50
4 321
5 983
See result in SQL FIDDLE.
You almost got the answer Left Outer Join is what you need but you missed to select Cr_memo from Credit_Memos table. Since you don't want to show Null values when there is no Invoices_ID in Credit Memos table use IFNULL to make NULL's as Empty string
SELECT A.ID, A.Amount, IFNULL(B.Cr_memo,'') AS Cr_memo
FROM Invoices AS A
LEFT JOIN Credit_Memos AS B
ON A.ID = B.invoice_ID
The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.
SELECT A.ID, A.Amount, IFNULL(B.amount,0) AS Cr_memo FROM Invoices AS A
LEFT JOIN Credit_Memos AS B ON A.ID = B.invoice_ID
here is some useful link about left join link and another

Query also returns column with value 0

I have two tables:
tb_question
**id_quest** | **desc_quest**
1 | How do you do...?
2 | How are you...?
tb_answer
**id_quest** | **date_answer**
1 | 2013/11/25
1 | 2013/11/26
1 | 2013/11/27
And my query:
SELECT
q.id_quest,
q.desc_quest,
COUNT(a.id_quest) as total_answer -- count total answer by question
FROM tb_question q
INNER JOIN tb_answer a
ON q.id_quest = a.id_quest;
Result:
ID_QUEST | DESC_QUEST | TOTAL_ANSWER
1 | How do you do...? | 3
How could it do to return also question id = 2 with 0 count ?
Expected result:
ID_QUEST | DESC_QUEST | TOTAL_ANSWER
1 | How do you do...? | 3
2 | How are you...? | 0
http://sqlfiddle.com/#!2/3bfe7/1
Two problems:
You have to use an outer join to get questions with no answers.
You left out the GROUP BY clause.
SELECT
q.id_quest,
q.desc_quest,
COUNT(a.id_quest) as total_answer
FROM tb_question q
LEFT OUTER JOIN tb_answer a ON q.id_quest = a.id_quest
GROUP BY q.id_quest
DEMO
dont use inner join to select all idquest, inner join to produce subset of table
SELECT tbq.id_quest,tbq.desc_quest,COUNT(tba.id_quest)
FROM tb_question tbq
LEFT OUTER JOIN tb_answer tba ON tba.id_uest=tbq.id_quest
GROUP BY tbq.id_quest
ORDER BY tbq.id_quest