WITH ROLLUP not showing sum - mysql

SELECT a.Store,
t.CM
FROM sales_data a
INNER JOIN (
SELECT Store, SUM(no_of_bill) AS CM
FROM cash_memo c
WHERE c.Bill_Date < '2018-02-28'
GROUP BY Store
) t USING (Store)
GROUP BY a.Store WITH ROLLUP
gives me the below result:
[query result][1]
I am not sure whats wrong that I am not getting the sum of 'CM' when using ROLLUP

The rollup needs to be with the group by. Try this:
SELECT Store, SUM(no_of_bill) AS CM
FROM cash_memo c
WHERE c.Bill_Date < '2018-02-28'
GROUP BY Store WITH ROLLUP;
Your query should fail with a syntax error because CM is not aggregated in the outer query and is not in the GROUP BY.
If you phrased the logic correctly, it would be:
SELECT a.Store, SUM(t.CM)
This would work and the ROLLUP would do what you expect.
Note: The JOIN seems unnecessary for the query. But if you really want it, you can just include it in the above query with no subquery.

You are using GROUP BY in the outer query without doing any aggregation.
Join the 2 tables, aggregate on the resultset returned by the join and use ROLLUP:
SELECT s.Store, SUM(c.no_of_bill) AS CM
FROM sales_data s INNER JOIN cash_memo c
ON c.Store = s.Store
WHERE c.Bill_Date < '2018-02-28'
GROUP BY s.Store WITH ROLLUP

Related

Mysql select query count & Distinct are not working properly

I am developing an eCommerce website using Laravel 8. I write the following script for find out total price & total quantity under a single order number. From following script getting the ERROR where is the problem please help me.
*At first I write row mysql then i will convert laravel query Builder.
SELECT COUNT (total_price) as totaPrice, COUNT (productqty) as proQnty
FROM (SELECT DISTINCT order_id FROM orderDetails)
LEFT JOIN ordertbl
ON ordertbl.id = orderDetails.order_id;
I guess you want to sum the prices and quantities, so use SUM() aggregate function.
Also you should do a LEFT join of ordertbl to orderDetails and not the other way around:
SELECT ot.id,
SUM(od.total_price) AS totaPrice,
SUM(od.productqty) AS proQnty
FROM ordertbl ot LEFT JOIN orderDetails od
ON ot.id = od.order_id
WHERE ot.id = ?
GROUP BY ot.id;
Or, without a join:
SELECT SUM(total_price) AS totaPrice,
SUM(productqty) AS proQnty
FROM orderDetails
WHERE order_id = ?;
Replace ? with the id of the order that you want.
In Your raw in missing the tablename alis for the subquery ..
Your raw query should be
SELECT COUNT(total_price) as totaPrice, COUNT(productqty) as proQnty
FROM (
SELECT DISTINCT order_id FROM orderDetails
) T
LEFT JOIN ordertbl ON ordertbl.id = T.order_id;

Implementing Count Function In SQL Query With Inner Joins

I have a query which is the following :
select person.ID, person.personName, round(avg(TIMESTAMPDIFF(DAY,orderDate,shippedDate)),2)) as 'Average' from orders inner join person person.personID= orders.personID where shippedDate is not null group by orders.personID;
The query above outputs 10 rows. I want to add a field which would count how how many rows there are in the query above in total.
I have tried to implement the SQL COUNT function but am struggling with the syntax as it has an INNER JOIN.
If you are running MySQL 8.0, you can do a window count:
select
person.ID,
person.personName,
round(avg(timestampdiff(day, o.orderDate, o.shippedDate)),2)) average,
count(*) over() total_no_rows
from orders o
inner join person p on p.personID = o.personID
where o.shippedDate is not null
group by p.personID, o.personName
Note that I made a few fixes to your query:
table aliases make the query easier to read and write
it is a good practice to qualify all column names with the table they belong to - I made a few assumptions that you might need to review
every non-aggregated column should belong to the group by clause (this is a good practice, and a requirement in most databases)
if you are not using Mysql 8.0 you can use Subquery:
select COUNT(*) FROM (
person.ID,
person.personName,
round(avg(TIMESTAMPDIFF(DAY,orderDate,shippedDate)),2)) as 'Average' from
orders inner join person person.personID= orders.personID where shippedDate
is not null group by orders.personID
);
and if you are using MYSQL 8.0 use window function like below:
select
person.ID,
person.personName,
round(avg(timestampdiff(day, o.orderDate, o.shippedDate)),2)) average,
count(*) over() total_no_rows
from orders o
inner join person p on p.personID = o.personID
where o.shippedDate is not null
group by p.personID, o.personName

Creating a join where I pull a count from another table

I have a table with real estate agent's info and want to pull firstname, fullname, and email from rets_agents.
I want to then get a count of all of their sales from a different table called rets_property_res_mstr.
I created a query that doesn't work yet so I need some help.
SELECT r.firstname, r.fullname, r.email
from rets_agents r
LEFT JOIN rets_property_res_mstr
ON r.email = rets_property_res_mstr.ListAgentEmail
LIMIT 10;

I'm not sure how to get the count in this.
You seem to be looking for aggregation:
SELECT a.firstname, a.fullname, a.email, COUNT(p.ListAgentEmail) cnt
FROM rets_agents a
LEFT JOIN rets_property_res_mstr p ON r.email = p.ListAgentEmail
GROUP BY a.firstname, a.fullname, a.email
ORDER BY ?
LIMIT 10;
Note that, for a LIMIT clause to really make sense, you need a ORDER BY clause so you get a deterministic results (otherwise, it is undefined which records will be shown) - I added that to your query with a question mark that you should replace with the relevant column(s).
I would consider using a CTE for this:
WITH sales as (
SELECT ListAgentEmail, count(*) count_of_sales
FROM rets_property_res_mstr
GROUP BY ListAgentEmail
)
SELECT r.firstname, r.fullname, r.email, count_of_sales
from rets_agents r
LEFT JOIN sales
ON r.email = sales.ListAgentEmail
LIMIT 10;

Group by does not provide accurate grouping

Attempting to create outputs that match the following screenshot:
When I attempt the following query:
SELECT t.amount, d.DOMAIN_NAME,td.month_number
FROM transaction t
JOIN transaction_date td ON t.trans_date_key = td.trans_date_key
JOIN domain d ON t.domain_key = d.domain_key
WHERE td.month_number =7
ORDER BY amount DESC;
I get the output of:
When I implement this query:
SELECT t.amount, d.DOMAIN_NAME,td.month_number
FROM transaction t
JOIN transaction_date td ON t.trans_date_key = td.trans_date_key
JOIN domain d ON t.domain_key = d.domain_key
WHERE td.month_number =7
GROUP BY domain_name
ORDER BY amount DESC;
I get the output of:
Why is my grouping only performing accurately on a few of the domain names, but not others?
You are not using GROUP BY correctly. You would need to use an aggregate function to sum the amounts. On the other hand, all non-aggregated columns should be listed in the GROUP BY clause.
Consider:
SELECT SUM(t.amount) total_amount, d.domain_name, td.month_number
FROM transaction t
INNER JOIN transaction_date td ON t.trans_date_key = td.trans_date_key
INNER JOIN domain d ON t.domain_key = d.domain_key
WHERE td.month_number = 7
GROUP BY d.domain_name, td.month_number
ORDER BY total_amount DESC;
What happens with the way you used GROUP BY is that MySQL actually picks a random record out of those that have the same domain_name. On most other RDBMS (and in non-ancient versions of MySQL), this would have generated a syntax error.

Is it possible to find COUNT function and then to show only certain values that are higher than 10

for example:
SELECT doctor.name
, doctor.surname
, COUNT(checkup.doctor)
FROM doctor
, checkup
WHERE doctor.id = checkup.doctor
GROUP
BY doctor.name
ORDER
BY checkup.doctor
this gives me list of all doctor that had checkup with patients, but i want to show only doctor with number of checkup more than 10 what to add to my sql
You want to limit your result rows according to an aggregation result. You'd do that in the HAVING clause.
As to your query: What is name? A unique name for every doctor? Otherwise better group by the ID - only then is this query valid according to the SQL standard. Then you are using a join syntax that we stopped using in the 1990s. Please use proper ANSI joins instead.
I prefer aggregating before joining, but that's just personal preference:
select d.name, d.surname, c.checkups
from doctor
join
(
select doctor as doctor_id, count(*) as checkups
from checkup
group by doctor
having count(*) > 10
) c on c.doctor_id = d.id
order by d.id;
You could just as well use
select d.name, d.surname, count(*) as checkups
from doctor d
join checkup c on c.doctor = d.id
group by d.id
having count(*) > 10
order by d.id;
TRY THIS: You can use HAVING clause to filter out the aggregation result and try to avoid outdated joins. Surname doesn't meaning there in GROUP BY so you use MAX to pick in select and remove from GROUP BY or leave as it is:
SELECT doctor.name
, doctor.surname
, COUNT(checkup.doctor)
FROM doctor
INNER JOIN checkup ON doctor.id = checkup.doctor
GROUP BY doctor.name, doctor.surname
HAVING COUNT(checkup.doctor) > 10
Do the fact you are using aggregation function as count If you want only the result with more then 10 COUNT(checkup.doctor)
you could filter the result using having
SELECT doctor.name,doctor.surname,COUNT(checkup.doctor)
FROM doctor
INNER JOIN checkup doctor.id=checkup.doctor
GROUP BY doctor.name
Having COUNT(checkup.doctor) > 10
ORDER BY COUNT(checkup.doctor)
the where clause work on the selecting row so don't know the result of an aggregated result .. for this SQL use the having clause that filter the result of a select
I think this will work for you:
SELECT
doctor.name, doctor.surname, checkup_stat.checkup_count
FROM
(SELECT doctor, COUNT(1) AS checkup_count FROM checkup GROUP BY doctor ORDER BY doctor) AS checkup_stat
RIGHT JOIN
doctor
ON
doctor.id = checkup_stat.doctor
WHERE
checkup_stat.checkup_count > 10;
Firstly, use a subquery to get the checkup count for every doctor.
Secondly, select the records from the subquery result where checkup count > 10.
Then, just join them together.