Combining Two Select Sum Statements Into One - mysql

I have two statements within my table which work fine individually like this:
SELECT fee_earner, (SUM(fe_fees)) AS Total
FROM fees
GROUP BY fee_earner
order by Total desc;
SELECT supervisor, (SUM(sv_fees)) AS Total
FROM fees
GROUP BY supervisor
order by Total desc;
But there are some cases where the fee_earner and supervisor fields have the same person as the data, is there a way to combine these two statements into one to get the overall totals?

You can use union all for this:
SELECT person, sum(fe_fees) as fe_fees, sum(sv_fees) as sv_fees,
(sum(fe_fees) + sum(sv_fees)) as total
FROM ((select fee_earner as person, fe_fees as fe_fees, 0 as sv_fees, 'earner' as which
from fees
) union all
(select supervisor as person, 0 as fe_fees, sv_fees as sv_fees, 'supervisor' as which
from fees
)
) t
GROUP BY person
order by Total desc;

select
fee_earner, SUM(fe_fees) as total, SUM(sv_fees) as total2,
SUM(fe_fees) + SUM(sv_fees) as wholeTotal
from
fees
group by
fee_earner, supervisor
order by
Total desc;

Related

SQL SELECT ID FROM MAX VALUE

i have 3 table,
- Employee (idemployee, iddivision, firstname, lastname)
- Salary (idsalary, idemployee, dateadded, amount)
- division (iddivision, divisionname)
i want to display the first name that have the highest amount between january and april
so far i tried
SELECT firstname, MAX(Total) FROM (
SELECT firstname,SUM(amount) AS Total
FROM salary
JOIN employee ON employee.idemployee=salary.idemployee
WHERE dateadded BETWEEN "2019-1-1" AND "2019-4-1"
GROUP BY employee.idemployee) as t
but the employeeid sql show is wrong. why?
SELECT employee.firstname, SUM(salary.amount) AS Total
FROM salary
JOIN employee
ON employee.idemployee=salary.idemployee
WHERE salary.dateadded BETWEEN "2019-01-01" AND "2019-04-01"
GROUP BY employee.firstname
ORDER BY 2 DESC
LIMIT 1
You are filtering by the range you want, then you sum the amounts in that range, grouping by the employee. If you order by that sum and get just the first row, it must he one what you are looking for.
Even better, if your employees just have a name in the firstname attribute, you have the risk to group by the same name wrongly. So, to identify better the employee, I would add the idemployee to the group by sentence. Like this:
SELECT employee.idemployee, employee.firstname, SUM(salary.amount) AS Total
FROM salary
JOIN employee
ON employee.idemployee=salary.idemployee
WHERE salary.dateadded BETWEEN "2019-01-01" AND "2019-04-01"
GROUP BY employee.idemployee,employee.firstname
ORDER BY 3 DESC
LIMIT 1
Do you mean you want it to be ordered from greatest to least?
SELECT firstname, Total FROM (
SELECT firstname,SUM(amount) AS Total
FROM salary
JOIN employee ON employee.idemployee=salary.idemployee
WHERE dateadded BETWEEN "2019-1-1" AND "2019-4-1"
GROUP BY employee.idemployee) as t
order by desc Total

SELECT the customer who has ordered the greatest quantity of Products in the case of two customers

I have the following ORDERS table
I know query to select the customer that has ordered the greatest quantity. However, how would it work, if say, two customers have the same quantity. What query should I write to show both the customers?
You can use a subquery which checks that the quantity for a given record matches the largest quantity observed in the table:
SELECT *
FROM yourTable
WHERE qty = (SELECT MAX(qty) FROM yourTable)
This will return multiple records if there are more than one customer sharing the maximum quantity.
If you only wanted to get back a single record, even in the presence of ties, you could use this approach:
SELECT *
FROM yourTable
ORDER BY qty DESC
LIMIT 1
I think you want sum of qty per custNum.
If so you can try like:
select custNum,
sum(qty) as qty
from Orders
group by custNum
order by sum(qty) desc;
Fiddle here:
http://sqlfiddle.com/#!9/47931b/10
SELECT custnum,sum(qty) as total
FROM orders
group by custnum
having sum(qty) = (SELECT MAX(qty) FROM orders);
This will return both values.

How to display only value that occurs second highest number of times?

Write a query to display the customer name who visited the second highest number of times
select customer_id,count(*) from booking group by customer_id ;
using this query i got the count of number of visits for each customer as shown below
CUSTOMER_ID,COUNT(*)
C001,6
C002,1
C003,1
C004,1
C005,4
but i want to display only c005 since he has visited the second maximum time
SELECT customer_id, COUNT(*)
FROM booking
GROUP BY customer_id
HAVING COUNT(*) <> (SELECT MAX(t.custCount)
FROM (SELECT COUNT(*) AS custCount
FROM booking
GROUP BY customer_id) t )
ORDER BY COUNT(*) DESC
LIMIT 1
As a side note, this won't work if there are ties for second place. In this case, you use the above query as a condition in the WHERE clause, e.g.
SELECT customer_id
FROM booking
GROUP BY customer_id
HAVING COUNT(*) = (query given above)
You can use a outer query and filter the same like
select customer_id from (
select customer_id,
count(*) as datacount
from booking
group by customer_id ) xxx
order by datacount desc
limit 1;

How to get a percentage of total sales without huge subquery in SELECT

I facing an issue of a way of calculating the total of the produced Amount column, so I can use it to calculate the
(user sales amount/total users sales amount) percentage ratio
SELECT * FROM Sales
ID Item Amount
5 IS1 10.00
5 IS2 2.00
3 IS1 10.00
2 IS3 7.00
9 IS5 6.00
Example 35.00
DESIRED OUTPUT
ID Amount Percentage
5 12.00 34.28571%
3 10.00 28.57142%
2 7.00 20.00000%
9 6.00 17.14285%
Example 35.00 100.0000%
SELECT ID, SUM(Amount) AS Amount
FROM Sales
GROUP BY ID
I have seen various examples on stack and other forums where people are using an additional select to calculate the total of amount column as such
SELECT ID, SUM(Amount) AS Amount,(SELECT SUM(Amount) FROM Sales) AS Total, Amount/(SELECT SUM(Amount) FROM Sales)*100 AS Percentage
FROM Sales
GROUP BY ID
But what do I do when my select query is huge, do you still put it in the select query or is there a better way this can be done.
SELECT a.ID, SUM(a.Amount) AS Amount, #rank:=#rank + 1 AS rank
FROM Sales a
INNER JOIN (SELECT #rank:=0) r
WHERE a.Item='IS1'
AND a.tdate='2015-01-20'
GROUP BY a.ID
ORDER BY Amount
The original query is actually longer than this, because it is also pulling in descriptions and values from other tables.
Essentially the original code of what I am doing, is going to the Sales table, pulling in all user sales data by current day, by product, by product sub_id, by transaction id. Then ranking who sold the highest amount of product, on the day, of a particular transaction id.
Of course this code gets huge, so I am not sure if it is right to add this whole code again in SELECT query to calculate a total?
Is there no way, it can calculate the total of amount without doing another query?
This will work on MSSQL, not sure about MySQL
Select distinct ID, SUM(AMOUNT) OVER (PARTITION BY ID) Amount, SUM(AMOUNT) OVER (PARTITION BY ID) / SUM(AMOUNT) OVER (PARTITION BY 1) * 100 Percentage
from Sales
order by ID
It provides you with your Desired Output as shown above.
try
declare #total_amt as decimal(18,5)
set #total_amt=(select sum(isnull(AMOUNT,0)) from Sales)
select Id,AMOUNT,(SUM(Amount)/(#total_amt)*100) as Percentage from Sales group by Id
I prefere a group by over a window function if it solves my problem:
SELECT a.ID, SUM(a.Amount) AS Amount, #rank:=#rank + 1 AS rank
, s.SumAll Total
, SUM(a.Amount)/s.SumAll*100 Percentage
FROM Sales a
, (SELECT #rank:=0) r
, (SELECT SUM(Amount) SumAll FROM Sales ) s
WHERE a.Item='IS1'
AND a.tdate='2015-01-20'
GROUP BY a.ID
ORDER BY Amount
Assuming sales is in reality a rather expensive view, you'll maybe better of with that (asuming mysql likes window functions):
SELECT a.ID, SUM(a.Amount) AS Amount
, #rank:=#rank + 1 AS rank
, SUM(Amount) OVER (Partition By 1) Total
, SUM(a.Amount)/SUM(Amount) OVER (Partition By 1)*100 Percentage
FROM Sales a
, (SELECT #rank:=0) r
WHERE a.Item='IS1'
AND a.tdate='2015-01-20'
GROUP BY a.ID
ORDER BY Amount
This query produces the desired output without a sub query in MySQL. SUM(Amount) OVER () gives you the total sum of Amount
SELECT ID, SUM(Amount) AS Amount,
SUM(Amount)*100/SUM(Amount) OVER () AS percentage
FROM Sales
GROUP BY ID

What is the best way to select rows with maximum value?

I have come across a task, I managed to complete the objective but the solution I got is not optimum, I need more optimum solution. I have used normal Sub Queries May be Correlated Sub Query can solve this better.
This is the table i made
SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid;
The output of this is like:-
What I want is the custid having maximum Total.
One way to do it is using Order by Total DESC LIMIT 1 but this will give only 1 result.
What I did is
SELECT custid
FROM (SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid) c1
WHERE total = (SELECT max(Total)
FROM (SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid) c2)
This gives me correct result that is
What I want to do is reduce the code, because here I am writing the same thing again. I know there must be a simpler way to do it. Maybe a correlated query.
Looking for some good answers. This is basically to clear my concepts only
Sorry, if it is noob question. I am a noob to SQL.
After understand what OP want with #Ravinder 's tip,
I guess build in mysql function GROUP_CONCAT is what you need, sql is:
select custid_count.Total, GROUP_CONCAT(custid_count.custid order by custid_count.custid asc SEPARATOR ',') as custids from
(select custid, count(distinct bid) as Total from loan group by custid order by Total desc) as custid_count
group by custid_count.Total
order by custid_count.Total desc
limit 1;
the result column custids is the max ids concated by ',' ,after the query, you need to split custids by ',' and convert each substring to number type you need,
Here is another way:
select * from loan
where custid =
(
select custid_count.custid from
(select custid, count(distinct bid) as Total from loan group by custid order by Total desc) as custid_count
order by custid_count.Total desc
limit 1
);
First find the custid with max count, then query all rows which match the custid,
I haven't tried this in mysql, but in the sql language I'm using it is fine to use a aggregation function without a group by so something like this
select custid, total, max(total) as maxtotal
from (select custid, count(distinct bid) as total
from loan
group by custid) c1;
would tag on every line both the individual customer total and the table wide max total, and you'd just have to filter on the ones that where the total was equal to the max total. That would give you a final answer of something like this:
select custid
from (select custid, count(distinct bid) as total
from loan
group by custid) c1
where total = max(total);