Sub-Query with group by and Case Statement - sql

I have two tables , one is Country table and another one is Threshold Table.
Country table has columns and data like this :
ID Country Count Year
00001 India 200 2011
00001 India 400 2013
00001 Japan 1000 2011
00001 Japan 550 2013
00001 China 400 2011
And the Threshold table has data like this :
ID Low Value High Value
00001 500 1000
That means if the Count >= 500 then Low , if the Count > 500 and < 1000 the Medium and if Count >= 1000 then High.
I want a result like this :
Country Count Threshold Low Value High Value
India 600 Medium 500 1000
Japan 1550 High 500 1000
China 400 Low 500 1000
So I want to write a SQL query .
I am already using this query :
SELECT C.Country,C.Count
,CASE WHEN C.Count <= T.Low_Value THEN 'Low' WHEN C.Count BETWEEN T.High_Value AND T.Low_Value THEN 'Medium' ELSE 'High' END AS Threshold,
T.Low_Value, T.High_Value FROM
(SELECT ID,Country,Sum(Count) AS Count
FROM Country
WHERE ID=00001
GROUP BY ID,Country) C
JOIN Threshold T
ON C.ID = T.ID
But this query is giving error.
Can anyone one please suggest me how to implement this ?
I am using Oracle
The error is ORA-00979 : not a GROUP BY expression
**This query is just for representation**

COUNT is a reserved word. Either pick a different alias or use double quotes around the alias.
SELECT C.Country,
C."Count",
CASE WHEN C."Count" <= T.Low_Value THEN 'Low'
WHEN C."Count" BETWEEN T.High_Value AND T.Low_Value THEN 'Medium'
ELSE 'High' END AS Threshold,
T.Low_Value,
T.High_Value
FROM (
SELECT ID,Country,Sum("Count") AS "Count"
FROM Country
WHERE ID=00001
GROUP BY ID,Country
) C
JOIN Threshold T
ON C.ID = T.ID

It can be done by using this :
SELECT Country
,Total
,CASE WHEN Total <= Low_Value THEN 'Low'
WHEN Total BETWEEN Low_Value AND High_Value THEN 'Medium'
ELSE 'High' END AS Threshold
FROM (SELECT ID
,Country
,Low_Value
,High_Value
,SUM(Count) Total
FROM (SELECT C.ID
,C.Country
,C.Count
,T.Low_Value
,T.High_Value
FROM Country C JOIN Threshold T
ON C.ID=T.ID
WHERE C.ID =00001)
GROUP BY Country,Low_Value,High_Value)

Related

Count results that have different column value related to same ID

I'm new to SQL and looking for help on how to best do this.
I have 2 tables with the following columns:
Investors: Round ID, Investor Name, Investor City, Investor Country
Rounds: Round ID, Company Name, Company City, Company Country
I joined them to get this result
Round ID
Investor Country
Company Country
1
US
Spain
1
UK
Spain
1
Spain
Spain
2
France
Germany
2
UK
Germany
3
UK
Italy
3
Italy
Italy
I will need to get the number of investors (per round ID) which have their country different from the Company Country, So like for Round 1 I will have 2, for Round 2 it's 0 and for round 3 it's 1.
How could I do this?
Thank you for your help!
Just use conditional aggregation:
select round,
sum(case when investor_country <> company_company then 1 else 0 end) as cnt
from t
group by round;
Looking at your expected output, I think you need the count = 0 in case there do not exists a single record for investor country = company country and if there is, then you need all other record count.
You can use conditions as follows:
select round_id,
case when count(case when investor_country = company_company then 1 end) = 0
then 0
else count(case when investor_country <> company_company then 1 end)
end as cnt
from your_table t
group by round_id;
If you need diffrent counts:
SELECT
RoundId,
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS Count
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
If you need difrent count and when all result of a same Round are difrent you want zero:
SELECT
t.RoundId,
IIF(t.Count = t.DiffrentCount,0,t.DiffrentCount) 'Count'
FROM
(
SELECT
RoundId,
SUM(1) AS 'Count',
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS 'DiffrentCount',
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
)t

sum positive and negative values separately

I have a table:
NAME MONEY
Jane 100
Chris -100
Jane 50
Ann -10
Jane -25
Ann 17
And i want to write a query to sum data, in one column should be only positive amount od money in another column only negative. Output should look like this:
NAME SUM_POSITIVE SUM_NEGATIVE
Jane 150 -25
Chris 0 -100
Ann 17 -10
query:
select name, sum(money) from TABLE where money>0 group by name
union
select name, sum(money) from TABLE where money<0 group by name;
shows nearly what i want, but result has duplicate names and two columns instead of three:
NAME SUM
Ann -10
Ann 17
Jane -25
Jane 150
Chris -100
Please help me rewrite my query to correct output.
use case when
select name, sum(case when money>0 then money end) SUM_POSITIVE
,sum(case when money<0 then money end) SUM_NEGATIVE
from TABLE group by name
You are getting duplicate name becase union operator merge only those rows where all column values are same, as Ann contain -10 and 17 which is distinct so its make duplicate
You can do conditional aggregation instead :
select name,
sum(case when money > 0 then money end) as SUM_POSITIVE,
sum(case when money < 0 then money end) as SUM_NEGATIVE
from TABLE
group by name;

SQL counting with condition

If I have a table called Buildings.
Room_No Bldg Capacity
112 SCEN 23
242 JBHT 25
542 SCEN 4
324 JBHT 24
What I want is to print out the Bldg name and the total number of rooms that have a capacity more than 20 in each building. So it is supposed to look like:
Bldg Total
SCEN 1
JBHT 2
Am I going on the right track:
Select Bldg, Count(Capacity > 20) as Total from Buildings Group By Total Desc
You could use CASE:
Select Bldg, Count(CASE WHEN Capacity > 20 THEN 1 END) as Total
from Buildings
Group By Bldg
ORDER BY Total DESC;
If you are using Postgresql you could rewrite it as:
Select Bldg, Count(1) FILTER(WHERE Capacity>20) as Total
from Buildings
Group By Bldg
ORDER BY Total DESC;
Rextester Demo
The other answers seem overly complicated for this problem. The solution is rather simple:
SELECT Bldg, COUNT(*) AS count
FROM Buildings
WHERE Capacity > 20
GROUP BY Bldg
Here is the Fiddle: http://sqlfiddle.com/#!9/308a6/1

Get the Data horizontally rather than vertically

Consider the query :
Select Dealer, Sales from DEALERDATA
where period in (201106,201107)
This will give result as:
DEALER SALES
Dealer1 100000
Dealer1 200000
Dealer2 600000
Dealer2 700000
I want result as
DEALER SALES SALES
Dealer1 100000 200000
Dealer2 600000 700000
If any one can let me know how this can be achieved?
Many thanks,
Sharon....
For a few number of columns you can use CASE combined WITH sum
SELECT Dealer
, SUM(CASE WHEN period=201106 THEN Sales ELSE 0 END) sales201106
, SUM(CASE WHEN period=201107 THEN Sales ELSE 0 END) sales201107
FROM DEALERDATA
WHERE period IN (201106,201107)
GROUP BY Dealer

Sql query Solution

I have a query as follows.
select strftime('%Y-%m',A.traDate) as Month,sum(A.TraAmt) as Total,C.GroupType from
TransactionTbl A left join TransactionCategory B on A.CategoryID = B.CategoryID left join
CategoryGroup C on B.CatGRoupID=C.CatGRoupID where A.UserID=1 and A.ProfileID=1 and
date(A.TraDate) between date('2009-12-01') and date('2010-11-01') group by C.GroupType,
strftime('%m',A.traDate) order by Month
Above query gives result as follows,
Month Total C.GroupType
----- ----- -----------
2009-12 4100 Expense
2009-12 8000 Income
2010-01 200 Expense
2010-01 2000 Income
2010-02 3500 Expense
2010-02 7500 Income
I want solution like this.
Month Income Expense
----- ----- -----------
2009-12 8000 4100
2010-01 8000 200
2010-02 7500 3500
I am trying hard to get output like this, but I could find any kind of solution.
This is one way of achieving what you want:
SELECT
T1.Month,
SUM(CASE T1.GROUPTYPE WHEN 'Income' THEN T1.TOTAL ELSE 0 END) AS Income,
SUM(CASE T1.GROUPTYPE WHEN 'Expense' THEN T1.TOTAL ELSE 0 END) AS Expense
FROM (/* Your query here */) AS T1
GROUP BY T1.Month