I am working with a table that has the following information for 20 different years
Income for citizens for a given year
Region which shows where the citizens live
Year which represents the income of the citizen in the current year
I am using a group by function in order to get average income level for each group,year. And recently I got help here (SQL Group by. Add new row with average result for all groups)
so I could add an extra row with avg income for all regions.
select avg(income),region,year,count(*) as population_size
from income_region group by region,year
union all
select avg(income),'All','All',count(*) as population_size from income_region
However, when I add in an extra column "year" to the group and try the "union all" solution for both year and region it only calculates the average income for all years and all regions.
Ideally I would also have the following types of new groups:
Average income when year = 2001
Average income when year = 2002' ...etc (for all years)
Average income for all years when region = 'North America'
Average income for all years when region = 'Europe'.. etc. (for all regions)
How can be this be done?
Try using with rollup:
select region, year, count(*) as population_size, avg(income)
from income_region
group by region with rollup;
You can refer to the documentation for more details.
just use rollup
select avg(income),region,year,count(*) as population_size
from income_region group by region with rollup
Related
Company_name
Quarter
Year
Revenue
TCS
Q1
2001
50
CTS
Q2
2010
60
ZOHO
Q2
2007
70
CTS
Q4
2015
90
This is my sample table where I store the names of the companies, quarters of the years, years and revenue for each year per a certain quarter.
I want to find the company with top revenue for each quarter, regardless of the year, and display its revenue too.
In the above case the resultant output should be something like this:
QUARTER
COMPANY_NAME
REVENUE
Q1
TCS
50
Q2
ZOHO
70
Q4
CTS
90
Here's what I've tried:
SELECT DISTINCT(C1.QUARTER),
C1.REVENUE
FROM COMPANY_REVENUE C1,
COMPANY_REVENUE C2
WHERE C1.REVENUE = GREATEST(C1.REVENUE, C2.REVENUE);
There are a couple of problems in your query, among which:
the fact that the DISTINCT keyword can be applied to full rows rather than single fields,
the SELF JOIN should be explicit, though most importantly it requires a matching condition, defined by an ON clause (e.g. SELECT ... FROM tab1 JOIN tab2 ON tab1.field = tab2.field WHERE ...)
Though probably you could solve your problem in another way.
Approach for MySQL 8.0
One way of computing values on partitions (in your case you want to partition on quarters only) is using window functions. In the specific case you can use ROW_NUMBER, which will compute a ranking over your revenues descendently for each selected partition. As long as you want the highest revenue for each quarter, you can select the row number equal to 1 for each quarter group.
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER(
PARTITION BY Quarter
ORDER BY Revenue DESC
) AS rn
FROM tab
)
SELECT Quarter,
Company_name,
Revenue
FROM cte
WHERE rn = 1
Check the demo here.
Approach for MySQL 5.7
In this case you can use an aggregation function. As long as you want your max "Revenue" for each "Quarter", you need first to select the maximum value for each "Quarter", then you need to join back to your original table on two conditions:
table's quarter matches subquery quarter,
table's revenue matches subquery max revenue
SELECT tab.Quarter,
tab.Company_name,
tab.Revenue
FROM tab
INNER JOIN (SELECT Quarter,
MAX(Revenue) AS Revenue
FROM tab
GROUP BY Quarter ) max_revenues
ON tab.Quarter = max_revenues.Quarter
AND tab.Revenue = max_revenues.Revenue
Check the demo here.
Note: the second solution will find for each quarter all companies that have the maximum revenue for that quarter, which means that if two or more companies have the same maximum value, both will be returned. This won't happen for the first solution, as long as the ranking ensures only one (the ranked = 1) will be retrieved.
You can just use a cte:
with x as (
select Quarter, max(Revenue) as Revenue
from table
group by Quarter
)
select t.Company_name, x.Quarter, x.Revenue
from x
join table t
on x.Revenue = t.Revenue
and t.Quarter = x.Quarter;
see db<>fiddle.
First you select the max Revenue group by Quarter, then I'm joining to the table on the returned max(Revenue) but as #lemon pointed out in comments that's not enough because what would happen when there's two revenues on same company but different quarters it will return more rows as shown in this db<>fiddle.
So that's why I need to add the join on quarter so it will only return one result per quarter.
But if you're using a version of MySql that doesn't support cte you can use a subquery like:
select t.Company_name, x.Quarter, x.Revenue
from
(
select Quarter, max(Revenue) as Revenue
from test
group by Quarter
) x
join test t
on x.Quarter = t.Quarter
and x.Revenue = t.Revenue;
Try this,
SELECT quarter, company_name,max(revenue) FROM table_name GROUP BY quarter
How do I query the following:
For each customer, product and month, count the number of sales transactions that were between the previous and the following month's average sales quantities. For January and December, display NULL or 0.
Can only use: 5 aggregate functions (sum, count, avg, max & min)
This is the table reference:
create table sales
(
cust varchar(20),
prod varchar(20),
day integer,
month integer,
year integer,
state char(2),
quant integer,
date date
);
Schema:
Example of my Desired Result
I am stuck with the following codes. I'm having a hard time how to execute it.
SELECT cust, prod, month, COUNT(*) AS SALES_COUNT_BETWEEN_AVGS
FROM sales
I use MySQL. Please guide me thank you.
Maybe try a query like below
the first part is to calculate averages using group by
second part is to use to those averages in a JOIN twice for past month and future month
third part is WHERE clause in which we compare data. Note we have used greatest and least functions to determine min and max between two values from past and next month
Query
WITH T AS
(SELECT cust, prod, month, AVG(quant) AS avg_quantity
FROM sales
group by cust, prod, month
)
SELECT S.cust, S.prod, S.month, COUNT(1) AS Sales_count
FROM sales S
LEFT JOIN T T1
ON T1.cust=S.Cust AND
T1.prod=S.Prod AND
T1.Month=S.Month-1
LEFT JOIN T T2
ON T2.cust=S.Cust AND
T2.prod=S.Prod AND
T2.Month=S.Month+1
WHERE S.quant BETWEEN IFNULL(LEAST(T1.avg_quantity,T2.avg_quantity),0) AND IFNULL(GREATEST(T1.avg_quantity,T2.avg_quantity),0)
I have a table with 3 fields, touristic places, the country they're in and the average rating by tourists for this place. I would like to compare different countries based on the average rating of their top touristic places. I use MySQL
It looks like this basically :
Eiffel Tower | France | 4,2
Trakoscan Castle | Croatia | 4,6
For example, how does the average of the notes of the 5 best touristic places in France compare with the average of the notes of the 5 best touristic places in Croatia. I know how to average all places for a country and compare that but I don't know how to combine LIMIT and GROUP BY
Thank you for your help.
You can use window functions to filter on the top 5 notes per country, then aggregate.
Assuming that your table has columns country, place and rating, you would phrase the query as:
select country, avg(rating) avg_rating_top5
from (
select t.*,
row_number() over(partition by country order by rating desc) rn
from mytable t
) t
where rn <= 5
group by country
Note that window functions are available in MySQL 8.0 only.
I feel like this is a stupid question, but I haven't been able to find a solution by searching. I have a dataset with sales data, where I want to group some of the ID groups together and show the sum of sales. I'm not concerned with individual items, I want to see only the groups of items and the sum of their sales.
A simplified version of what I'm doing now is:
SELECT year, quarter, company, segment, sum(sales) AS total_sales
FROM table
WHERE segment = 001 OR segment = 015
AND producer LIKE '%ACME Inc.%'
AND year = 2015 OR year = 2016
GROUP BY quarter, year, producer, segment
ORDER BY year, quarter, producer, segment ASC
;
My main problem is getting segments 001 and 015 into the same group, for instance 'Jelly' so that the output shows
year|quarter|company|segment|total_sales
2015|1|ACME Inc.|Jelly|100
where 'Jelly' includes both segments 001 and 015.
I'm able to list alle the individual items, but not group them up with in aggregated groups. My problem is being able to filter only the companies I want to look at, and only the segments I want to look at, at the same time as I'm creating and listing custom groups of the segments.
Thanks for any help :)
Edit: MCVE here - http://sqlfiddle.com/#!9/2414bd/3
CREATE TABLE Table1
(`company` text, `sales` int, `year` int, `quarter` int,
`segment` text)
;
INSERT INTO Table1
(`year`, `quarter`, `company`, `segment`, `sales`)
VALUES
(2015,1,'ACME',001,100),
(2015,1,'ACME',015,100),
(2015,1,'HAL',001,25),
(2015,1,'HAL',015,25),
(2015,1,'ACME',002,50),
(2015,1,'HAL',003,50)
/*many other companies and segments as well*/
;
First, I think you need to fix your where clause. Numbers that start with 0 are usually strings. Plus, you should be using in and careful about the and/or logic:
SELECT year, quarter, company, segment, sum(sales) AS total_sales
FROM table
WHERE segment IN ('001', '015') AND
producer LIKE '%ACME Inc.%' AND
year IN (2015, 2016)
GROUP BY quarter, year, producer, segment
ORDER BY year, quarter, producer, segment ASC;
Next, if you want to combine segments, use case. You seem to want:
SELECT year, quarter, company, 'Jelly' as segement,
SUM(sales) AS total_sales
FROM table
WHERE segment IN ('001', '015') AND
producer LIKE '%ACME Inc.%' AND
year IN (2015, 2016)
GROUP BY quarter, year, producer
ORDER BY year, quarter, producer ASC;
SELECT year, quarter, company,
CASE
WHEN segment IN (001,015)
THEN 'Jelly'
WHEN segment IN (002,003)
THEN 'Bread' ELSE segment END segment,
SUM(sales) AS total_sales
FROM Table1
WHERE company LIKE '%ACME%' OR company LIKE '%HAL%'
AND year IN (2015,2016)
GROUP
BY year
, quarter
, company
, CASE WHEN segment IN (001,015) THEN 'Jelly'
WHEN segment IN (002,003) THEN 'Bread'
ELSE segment
END
ORDER
BY year, quarter, company, segment ASC
;
I need to write a SQL query to calculate the difference in revenues between Europe and Asia. I am constrained by the app dev and cannot calculate this in 2 steps (compute the totals in each continent separately then calculate the difference)
Here is the db:
Sales(s_key, s_key, s_product, s_date, s_amount, s_quantity)
Customer(c_key, c_name, c_city, c_country, c_continent)
Can you help me extend this query which calculates the revenue in Europe to get difference with revenue in Asia?
Thank you!
Select Sum(s_amount)
From Sales
Where c_continent = 'Europe'
Group By c_continent
select sum(case s_continent
when 'Europe' then s_amount
when 'Asia' then -s_amount
end) as EuropeMinusAsia
from Sales