How to count in mysql - 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.

Related

MySQL Summing & Counting Child Values in Another Table

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

join one row to all row and returning all row

can I get data like this from my table
| id_outlet| date | count(msisdn) |
| 34.10.1 | 2014-08 | 0 |
| 34.10.1 | 2014-09 | 3 |
| 34.10.1 | 2014-10 | 2 |
| 34.10.2 | 2014-08 | 1 |
| 34.10.2 | 2014-09 | 0 |
| 34.10.2 | 2014-10 | 0 |
So I have 2 tables
1. table outlet (unique)
2. table sales (detail of table outlet)
As u see in my second table there are 3 periode (2014-08, 2014-09, 2014-10)
I want join that periode with id_outlet in first table like that example.
Can I?
Please Help me
Using a CROSS JOIN:-
SELECT
o.id_outlet,
s_main.periode,
o.branch,
count(msisdn)
FROM
(
SELECT DISTINCT SUBSTRING(date,1,7) AS periode
FROM sales
) s_main
CROSS JOIN outlet o
LEFT OUTER JOIN sales s
ON s_main.periode = SUBSTRING(s.date,1,7)
AND o.id_outlet = s.id_outlet
WHERE (o.STATUS LIKE 'STREET%')
GROUP BY s_main.periode, o.branch, o.id_outlet
If you have a table of dates then you can just use that rather than the sub query to get the dates (which also avoids the potential problem of not having a date in the results for a month where there has been zero sales for any outlet).
Don't worry, be happy!
SELECT
o.id_outlet,
SUBSTRING(s.date,1,7) AS periode,
o.branch
FROM outlet o LEFT JOIN sales s ON o.id_outlet = s.id_outlet
WHERE (o.STATUS LIKE 'STREET%')
ORDER BY o.id_outlet, YEAR(s.DATE), MONTH(s.DATE), branch
You need this query:
SELECT
o.id_outlet,
d.period AS periode,
o.branch,
count(msisdn)
FROM dates d LEFT JOIN outlet o ON d.period = SUBSTRING(o.date,1,7) LEFT JOIN sales s ON o.id_outlet = s.id_outlet
WHERE (o.STATUS LIKE 'STREET%')
GROUP BY CONCAT(d.period, '#', s.id_outlet)
ORDER BY o.id_outlet, d.period, branch

MySQL Filtering rows from three tables

Let's say i've got this database:
book
| idBook | name |
|--------|----------|
| 1 |Book#1 |
category
| idCateg| category |
|--------|----------|
| 1 |Adventures|
| 2 |Science F.|
book_categ
| id | idBook | idCateg | DATA |
|--------|--------|----------|--------|
| 1 | 1 | 1 | (null) |
| 2 | 1 | 2 | (null) |
I'm trying to select only the books which are in category 1 AND category 2
This is what I've got so far:
SELECT book.* FROM book,book_categ
WHERE book_categ.idCateg = 1 AND book_categ.idCateg = 2
Obviously, this giving 0 results becouse each row has only one idCateg it does work width OR but the results are not what I need. I've also tried to use a join, but I just can't get the results I expect.
Here it's the SQLFiddle of my current project, the data at the begining is just a sample.
SQLFiddle
Any help will be really appreciated.
You could double join with a constraint on the category id:
SELECT a.* FROM book AS a
INNER JOIN book_categ AS b ON a.idBook = b.idBook AND b.idCateg = 1
INNER JOIN book_categ AS c ON a.idBook = c.idBook AND c.idCateg = 2
You could use a subquery:
SELECT a.* FROM book AS a
WHERE
(SELECT COUNT(DISTINCT idCateg) FROM book_categ AS b
WHERE b.idBook = a.idBook AND b.idCateg IN (1,2)) = 2
If you are on MySQL as your fiddle implies, you should prefer the join variant, since most joins are much faster in MySQL than subqueries.
edit
This one should also work:
SELECT a.* FROM book a
INNER JOIN book_categ AS b ON a.idBook = b.idCateg
WHERE b.idCateg IN (5, 6)
GROUP BY idBook
HAVING COUNT(DISTINCT b.idCateg) = 2
and should be faster than the two above, although you have to change the last number according to the number of category ids you are requesting.

MySQL subselect in query

I would like to get the following results from my query:
id_product_attribute | id_product | reference | name | total
12 | 1 | 234235 | product_name | 2
14 | 2 | 235435 | product_name | 7
16 | 3 | 235325 | product_name | 4
etc
but when I use this query:
select pa.id_product_attribute, p.id_product, pa.reference, cl.name, sum(od.product_quantity) as total
from ps_product_attribute pa
left join ps_order_detail od on od.product_attribute_id = pa.id_product_attribute
left join ps_product p on pa.id_product = p.id_product
left join ps_category_product cp on cp.id_product = p.id_product
left join ps_category_lang cl on cp.id_category = cl.id_category
where cp.id_category = 141 and cl.id_lang = 6;
it gives me only this results:
id_product_attribute | id_product | reference | name | total
12 | 1 | 234235 | product_name | 13
so in the 'total' column it shows me the total of all, instead of seperate per row.
can anyone tell me what I'm doing wrong in my query?
Your source data would help, but at the very least you forgot to GROUP BY at the end. With the current query, you should add;
GROUP BY pa.id_product_attribute, p.id_product, pa.reference, cl.name
With MySQL, you can choose to GROUP BY less columns and get a random selection of values in the other ones, but if possible, you should GROUP BY all columns that don't have aggregates (like SUM in this case) on them.
Aggregate functions should be used with GROUP BY CLAUSE

MySQL UNION Only Includes First Table

I need to perform a FULL OUTER JOIN on two tables and I'm trying to implement it in MySQL using the LEFT JOIN/RIGHT JOIN/UNION ALL technique.
Here are the original tables:
giving_totals:
+--------------+---------------+-------------+
| country_iso2 | total_given | supersector |
+--------------+---------------+-------------+
| AE | 1396986989.02 | 3 |
| AE | 596757809.20 | 4 |
| AE | 551810209.87 | 5 |
| AE | 25898255.77 | 7 |
| AE | 32817.63 | 9 |
...
+--------------+---------------+-------------+
receiving_totals:
+--------------+----------------+-------------+
| country_iso2 | total_received | supersector |
+--------------+----------------+-------------+
| AE | 34759000.00 | 3 |
| AE | 148793.82 | 7 |
| AE | 734.30 | 9 |
| AF | 6594479965.85 | 1 |
| AF | 2559712971.26 | 2 |
+--------------+----------------+-------------+
I want the resulting table to have one entry for each country for each supersector code even if it did not give or receive money for that sector (this is from the AidData project dataset in case anyone is familiar.) I thought to accomplish this by doing a UNION of a LEFT JOIN (to get all giving entries) and RIGHT JOIN (to get all receiving entries.) Here's the query I tried:
SELECT g.country_iso2 AS country_iso2, g.total_given AS `total_given`,R.total_received AS `total_received`,g.supersector AS `supersector`
FROM (`giving_totals` `g`
LEFT JOIN `receiving_totals` `r`
ON(((g.country_iso2 = r.country_iso2)
AND (g.supersector = r.supersector))))
UNION ALL
SELECT g.country_iso2 AS country_iso2, g.total_given AS `total_given`,R.total_received AS `total_received`,g.supersector AS `supersector`
FROM (`giving_totals` `g`
RIGHT JOIN `receiving_totals` `r`
ON(((g.country_iso2 = r.country_iso2)
AND (g.supersector = r.supersector))))
But this only returns the first join, whether or not I put the right or left join first. I think I may be misunderstanding the UNION operation because the individual joins each return what I expected. Any help is appreciated as always.
Here is an alternative method to do a full outer join:
SELECT driver.country_iso2 AS country_iso2,
g.total_given AS `total_given`,
R.total_received AS `total_received`,
driver.supersector AS `supersector`
from ((select distinct country_iso2, supersector
from giving_totals
) union
(select distinct country_iso2, supersector
from receiving_totals
)
) driver left outer join
giving_totals gt
on gt.country_iso2 = driver.country_iso2 and
gt.supersector = driver.country_iso2 left outer join
receiving_totals rt
on rt.country_iso2 = driver.country_iso2 and
rt.supersector = driver.country_iso2
That is, do the union as a subquery to get all the combinations you are interested in. Then you can do a left outer join to that table.
The reason for your problem is that aliases in the second query. You can try this instead:
SELECT r.country_iso2 AS country_iso2, g.total_given AS `total_given`,R.total_received AS `total_received`,r.supersector AS `supersector`
FROM (`giving_totals` `g`
RIGHT JOIN `receiving_totals` `r`
ON(((g.country_iso2 = r.country_iso2)
AND (g.supersector = r.supersector))))
The original form would have NULLs for these values.