Sum of column depending on values - sql

Can you guys let me know how to make a query that output the sum of amount based on column values(order, Continent and Country)? Also, I want to show all Continent values as unique value (North America)
Example table,
ID Code Continent Country amount
----------------------------------------------------
1 1 North America NULL NULL
2 1 America USA 10
3 1 NA USA 10
4 1 Unknown USA 10
5 2 North America NULL NULL
6 2 America Canada 15
7 2 NA Canada 15
8 2 Unknown Canada 15
9 3 North America NULL NULL
10 3 America Mexico 20
11 3 NA Mexico 20
12 3 Unknown Mexico 20
Output
ID Code Continent Country SumAmount
----------------------------------------------
1 1 North America USA 30
2 2 North America Canada 45
3 3 North America Mexico 60
I have tried to approach it like
select ID, Code, case when Continent != 'North America' then Continent = 'North America' end as Continent, Country, sum(Amount) as SumAmount
from Table group by ID, Continent, Country
or maybe I need to make a query like this and work with this query below?
select ID, Code, Continent, Country, sum(Amount) as SumAmount
from Table where Continent !='North America'
But it is not working. How should I do this?
I appreciate for any other approaches. It would be better than mine

The awkward design here (relations with no real indication of such other than the shared Code column) is going to lead to suboptimal queries like this
DECLARE #ContinentToReport varchar(32) = 'North America';
;WITH x AS
(
SELECT Code FROM dbo.TableName
WHERE Continent = #ContinentToReport
AND Country IS NULL
)
SELECT ID = ROW_NUMBER() OVER (ORDER BY x.Code),
x.Code,
Continent = #ContinentToReport,
t.Country,
SumAmount = SUM(t.amount)
FROM dbo.TableName AS t
INNER JOIN x ON t.Code = x.Code
WHERE t.Country IS NOT NULL
GROUP BY x.Code, t.Country
ORDER BY x.Code;
Output (though I made a guess at what ID means and why it's different then the ID and the source, and I find the Continent column is kind of redundant since it will always be the same):
ID
Code
Continent
Country
SumAmount
1
1
North America
USA
30
2
2
North America
Canada
45
3
3
North America
Mexico
60
Example db<>fiddle

The simplest query which returns the correct result seems to be something like this
select row_number() over (order by Code) ID,
Code,
'North America' Continent,
Country,
sum(amount) SumAmount
from dbo.TableName
where Country is not null
group by Code, Country
order by Code;
dbFiddle

Related

Unexpected result of SQL query with ALL in PostgreSQL

I have a very simple table countries(name, gdp, continent) with data I collected from Wikipedia (actually, doesn't really matter). If I want to know how many countries each continent has with
SELECT continent, COUNT(*) AS cnt
FROM countries
GROUP BY continent;
I get the following result:
continent | cnt
---------------+-----
Africa | 56
Asia | 46
South America | 12
North America | 22
Europe | 46
Oceania | 14
So I have for each content the corresponding countries. In any case, there are only 196 rows so the data is very small.
No I want to use a query to get for each continent the country with the largest GDP. The query is also very simple and looks like this:
SELECT name, continent, gdp
FROM countries c1
WHERE gdp >= ALL (SELECT gdp
FROM countries c2
WHERE c2.continent = c1.continent);
However, the result I get is:
name | continent | gdp
----------------------------+---------------+----------------
Australia | Oceania | 1748000000000
Brazil | South America | 1810000000000
People's Republic of China | Asia | 19910000000000
United States | North America | 25350000000000
In short, the corresponding countries for Europe and Africa are missing. By looking at the data, the countries with the highest GDP is Germany, but I don't understand why it's not part of the result set.
As a test, if I run the query
SELECT continent, MAX(GDP) AS max_gdp
FROM countries
GROUP BY continent;
I correctly get 6 GDP values for each continent (incl. the correct value for Germany):
continent | max_gdp
---------------+----------------
Africa | 498060000000
Asia | 19910000000000
South America | 1810000000000
North America | 25350000000000
Europe | 4319000000000
Oceania | 1748000000000
Why is the ALL query missing the 2 rows for the European and African countries?
The problem turned out to be NULL values, as a_horse_with_no_name suspected.
Note that there is a more performant way to write this query in PostgreSQL:
SELECT DISTINCT ON (continent)
name, continent, gdp
FROM countries
ORDER BY continent, gdp DESC NULLS LAST;
For each continent, that will output the first row in ORDER BY order.

How to sum values if I don't have column to group it by

I need to sum sales grouped by country, but I have to group them manually because I don't have any other way.
Unfortunately, I don't have the column 'continent', but there are not too many countries on the list so I can do it manually. I can't create any new columns in the table, so I need to do it in a query.
For example:
country | sum of sales
Germany 1000
Italy 500
Canada 700
UK 1300
USA 3000
I would like to see the total sales for Europe and North America
continent | sum of sales
Europe 2800
North America 3700
You should be able to combine case expression and in predicate, something along this lines:
SELECT CASE
WHEN country in ('Germany', 'UK') THEN 'Europe'
WHEN country in ('Canada', 'USA') THEN 'North America'
END as continent,
sum("sum of sales")
FROM table
GROUP BY 1

I wonder how it works when multiple group by, like group by column_name(1), column_name(2), column_name(3)

When i checked it, it doesn't remove duplication of value. Why?
example) Group by a , Group by a,b,c
Is there a difference between Group by a, Group by a,b,c ?
I wrote SQL query like this ::
SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country;
result ::
Table: Customers
COUNT(CustomerID) Country
---------------------------------
3 Argentina
2 Austria
2 Belgium
9 Brazil
3 Canada
2 Denmark
2 Finland
to
SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country, CustomerID;
Table: Customers
COUNT(CustomerID) Country
---------------------------------
1 Germany
1 Mexico
1 Mexico
1 UK
1 Sweden
1 Germany
1 France
Why doesn't tie same value changed query from Column_name?
It display all value along column_name.
I wonder if it works. thank you.

How do i indent the output so that the countries are indented 2 spaces?

This is the query that returns to me the output of region id in the left column, region_name in the right column as well as the countries that fall under that region but i want to make the countries indented a couple of spaces...
SELECT region_id, region_name
FROM
(
SELECT r.region_id, r.region_name, 0 AS ent
FROM regions r
UNION ALL
SELECT r.region_id, c.country_name, 1 AS ent
FROM regions r
INNER JOIN countries c
ON r.region_id = c.region_id
)
ORDER BY region_id, ent, region_name;
1 Europe
1 Belgium
1 Denmark
1 France
1 Germany
1 Italy
1 Netherlands
1 Switzerland
1 United Kingdom
2 Americas
2 Argentina
2 Brazil
2 Canada
2 Mexico
2 United States of America
This should work:
SELECT r.region_id, CONCAT(' ', c.country_name), 1 AS ent
You might need to add an AS clause for the combined field to put it all together.

Using HAVING with GROUPING SETS

My sql string as below
SELECT Country, City, COUNT(*) AS [Count]
FROM CountriesAndCities
GROUP BY GROUPING SETS ( ( Country, City ), ( Country) )
ORDER BY Country, City
I am getting results as below
Country City CountryCount
---------- ---------- ------------
France NULL 4
France Paris 4
Spain NULL 6
Spain Barcelona 3
Spain Madrid 3
If country has got only one city record, can I get results as below with using HAVING
Country City CountryCount
---------- ---------- ------------
France Paris 4
Spain NULL 6
Spain Barcelona 3
Spain Madrid 3
SELECT Country, City, COUNT(*) AS [Count]
FROM CountriesAndCities
GROUP BY GROUPING SETS ( ( Country, City ), ( Country) )
HAVING GROUPING(City) = 0
OR COUNT(DISTINCT City) > 1
ORDER BY Country, City
GROUPING(City) = 0 if City one of the fields currently being grouped by.
Conversely, when GROUPING(City) = 1 then City is reported as NULL.
This means that we always include the rows where the City is mentioned (not NULL).
For the other rows, where GROUPING(City) = 1 aka City IS NULL, then we only include the row if more than one City has been aggregated in to the result.