How to devide sum groups from one column by another column? - mysql

Suppose I have this table I want to query a person and the result should be to get sum of numbers devided by country's total
Country person number
USA A 3
USA A 2
USA C 2
RUS B 1
RUS C 3
IND A 2
DEU A 1
DEU D 1
Suppose I query person A
I want to get
USA 5/7
IND 2/2
DEU 1/2
SUM OF NUMBER / SUM OF COUNTRY
for person A
Now suppose I want to complicate things even further.. suppose I have a month column I want to get for each month these results

You can use conditional aggregation and /:
select country,
sum(case when person = 'A' then number else 0 end) / sum(number)
from t
group by country;

You can try the below -
DEMO
select country, person, sum(number) sum_of_number,
(select sum(number) from t t1 where t.country=t1.country) sum_of_country
from t
where person='A'
group by country, person

Related

MYSQL : Get data from multiple table using JOIN and UNION in single row

I have three database tables ‘customer’, ‘billing’, and ‘transaction’
customer:
cuid
name
address
1
David
City 1
2
Roja
City 2
billing :
id
cuid
month
bill_amount
1
1
1
100
2
1
2
200
3
2
1
400
4
1
3
100
transaction:
id
cuid
date
received_amount
1
1
2022-3-02
250
2
2
2022-2-02
200
3
2
2022-3-02
200
I need a new generated Due table after calculating month wise due amount using FIFO like this:
cuid
Name
Address
Month
Due_Amount
1
David
City 1
2
50
1
David
City 1
3
100
This code did not work properly. MySql Code:
SELECT
due.cuid,
due.Name,
due.Address,
due.Month,
sum(due.Amount - due.Received) AS Due_Amount
FROM
(SELECT
c.cuid,
c.name AS name,
c.address AS address,
b.month AS Month,
0 AS Received,
b.bill_amount AS Amount
FROM
customer c
INNER JOIN billing b ON c.cuid=b.cuid
UNION ALL
SELECT
c.cuid,
c.name AS Name,
c.address AS Address,
null AS Month,
t.received_amount AS Received,
0 AS Amount
FROM
customer c
INNER JOIN transaction t ON c.cuid = t.cuid) AS due
GROUP BY
due.cuid;
Code generated table is :
cuid
Name
Address
Month
Due_Amount
1
David
City 1
1
150
2
Roja
City 2
1
0
You probably don't need all that SUM(), UNION ALL and subquery. You can do it in a single query and JOIN all three tables like this:
SELECT c.cuid,
c.Name,
c.Address,
b.Month,
t.received_amount-b.bill_amount AS Due_Amount
FROM customer c
JOIN billing b
ON c.cuid=b.cuid
JOIN transaction t
ON c.cuid=t.cuid
AND b.month=MONTH(t.date);
Demo fiddle
I do have a slight curiosity though because my understanding of Due_amount is the remaining amount need to be paid by the customer and yours doesn't seem to be one. If it is, then the value should be negative because the customer David paid more (received_amount) than the bill_amount.

LIMIT and Group By? How do I return the lowest 100 earning customers by country? SQL

Hi I’ve a table database1
3 columns : customer_id , income , country
Customer_id
1001
1002
...
Income
5000
6000
7000
Country
SG
HK
VN
...
How do I write a query that returns the lowest 100 earning customers per country?
Is it possible to return:
Customer ID | country code
1003 SG
1004 SG
...
1007 VN
...
So on
Thanks!
On mySQL 8 you can leverage a window function for this:
SELECT * FROM
(
SELECT
country,
customer_id,
row_number() over(partition by country order by income asc) earn_rank
FROM table
)x
WHERE x.earn_rank <= 100
You can conceive that this window function will sort the rows by country then by income, then start counting up from 1. Each time the country changes the row numbering starts over from 1 again. This means that for every country there will be a row numbered 1 (with the lowest income), and a 2, 3 etc. If we then wrap it up in another outer query that selects only rows where the number is less than 101 we get 100 rows per country

MS Access: Count instances over field based on record-level criteria

I need a query to count the number of orders shipped to each state for each customer. So, let's say John had 5 orders: 2 to Florida, 2 to Alaska, and 1 to Kansas. How do I get those counts for each Customer. I have a query that provides me Customer and Order delivery state, but I cannot figure out how to get the counts. I am looking for something like:
>John FL 2
>John FL 2
>John AK 2
>John KS 1
>John AK 2
>...[Next Customer]...
Thank you.
You need to group it by customer and state and count based on this:
SELECT Customer, State, Count(*) AS Amount
FROM Orders
GROUP BY Customer, State
The resulting calculated field, is named Amount in this example.

How to group by on a highest value

So, for example i've got the following table;
ID COUNTRY VALUE
--------------------- -------------------- --------------------
1 India 12000
2 India 11000
3 UK 11000
4 India 15000
5 Canada 11000
And I would like to group by Country but only have the country with the highest value show up, if I would just use a group by query like:
SELECT * FROM countries GROUP BY country
I would get;
ID COUNTRY VALUE
--------------------- -------------------- --------------------
1 India 12000
3 UK 11000
5 Canada 11000
Where the value for india would be 12000. I would like the query to group on the highest value for the group by on country like:
ID COUNTRY VALUE
--------------------- -------------------- --------------------
3 UK 11000
4 India 15000
5 Canada 11000
So it's grouped on the highest value which is 15000.
DEMO
SELECT s1.ID, s1.COUNTRY, s1.VALUE
FROM countries s1
LEFT JOIN countries s2
ON s1.VALUE < s2.VALUE
AND s1.COUNTRY = s2.COUNTRY
WHERE s2.COUNTRY IS NULL;
OUTPUT
NOTE: But be carefull of ties. In that case you can get one random from those ties.
You can use the MAX aggregate function.
select
country,
max(value) value
from countries
group by
country
See the live example.
Edit: The original solution was only correct due to the nature of the data. I've removed the ID from the first query, to correct the mistake. Here is another solution (based on #Juan Carlos Oropeza's work - thank you) that will return the ID and eliminate the ties.
select
min(x.id) id,
x.country,
x.value
from (
select
c.*
from countries c
left join countries c1 on c.value < c1.value and c.country = c1.country
where c1.country is null
) x
group by
x.country,
x.value
;
See the live example - I've modified the data to cover edge cases mentioned above.

how can combine two columns in the same table and count its unique occurrences

I have been struggling and would really appreciate some assistance:
I have two tables cars and rides
cars
car_id car_manuf car_model
1 Honda CRV
2 Honda Accord
3 Toyota Corolla
4 Toyota Camry
5 Ford Fusion
rides
ride_id car_id ride_destination
1 3 Boston
2 5 New York
3 5 Washington DC
4 1 California
5 2 Dallas
6 5 Canada
I would like to count the number of rides by each car type which will have the combination of car_manuf and car_model and should be sorted from most to fewest number of rides.
Output should be:
CarType-NumberofRides
Honda_CRV-1
Honda_Accord-1
Toyota_Corolla-1
Toyota_Camry-0
Ford_Fusion-3
Sorted output with most-few rides
CarType-NumberofRides
Toyota_Camry-0
Honda_Accord-1
Toyota_Corolla-1
Honda_CRV-1
Ford_Fusion-3
mycode:
select
c.car_manuf + '_' + c.car_model AS 'Car Type',
(select count(*) from rides r where r.car_id = c.car_id) AS 'Number of Rides'
from cars c;
I am kinda stuck here and not sure which direction I should go in regards to getting the correct output.
You have to use GROUP BY and an ORDER BY when COUNTing the occurences. I use CONCAT to concatenate the strings instead of a + sign. Makes clearer what is going on, and is not mistaken as an arithmetic operation.
SELECT CONCAT(c.car_manuf, '_', c.car_model) AS CarType, COUNT(r.car_id) AS NumberOfRides
FROM rides r
LEFT JOIN cars c ON (r.car_id = c.car_id)
GROUP BY CarType
ORDER BY NumberOfRides ASC
However this omits the 0 occurences.
If you want to see the 0s as well swap the table order to:
SELECT CONCAT(c.car_manuf, '_', c.car_model) AS CarType, COUNT(r.car_id) AS NumberOfRides
FROM cars c
LEFT JOIN rides r ON (r.car_id = c.car_id)
GROUP BY CarType
ORDER BY NumberOfRides ASC