SQL Server Pivot clause with Count - sql

I'm using Microsoft SQL Server and trying to write the following query below. I want to use the Pivot clause to get the count in gold medals for USA and Russia from the Olympics 2000. But My output is Zero for both countries. I know that I can use the group by to get the desired result (see print screen below). But how can do this with the pivot clause?
Please see print screens of the dataset and the output below
select
'Gold' as total_m,
['USA'] as USA, ['RUS'] as RUS
from
(select
country, medal, year
from
summer
where
medal = 'Gold'
and year = 2000
and country in ('USA', 'RUS')) as SourceTable
pivot
(count(medal)
for country in (['USA'],['RUS'])) as PivotTable;
Dataset
Output
Group by

Remove quotes from pivot column list,
select 'Gold' as total_m, [USA] as USA, [RUS] as RUS
from
(select country, medal, year
from summer
where medal = 'Gold'
and year = 2000
and country in ('USA', 'RUS')) as SourceTable
pivot
(count(medal)
for country in ([USA],[RUS])) as PivotTable;

I find that it is simpler to express this with conditional aggregation. This is a portable syntax, that works across most databases, and that is somehow less convoluted that vendor-specific pivot syntax:
select mdel,
sum(case when country = 'USA' then 1 else 0 end) as USA,
sum(case when country = 'RUS' then 1 else 0 end) as RUS
from summer
where medal = 'Gold' and year = 2000 and country in ('USA', 'RUS')
group by medal

Related

Select only values from one column in a table in SQL with condition

Is it possible to get only the countrys who just played in the pre round
Country Round
Germany Pre Round
Germany Quater final
Spain Pre Round
Portugal Pre Round
And I just want to get the countrys which only played in the pre round. So the result should look like this:
Country
Spain
Portugal
You can group by country and set the conditions in the having clause:
select country
from tablename
group by country
having count(*) = 1 and max(round) = 'Pre Round'
You can try the below using not exists
select country from c
where not exists
(select 1 from c as c1 where c.country=c1.country and roundval<>'Pre Round')
Two more for fun. The first is kind of a variation on #forpas', assigning a numeric value to each round, representing the progression through the rounds, and then getting the highest for the country (which would be simpler if the rounds were stored separately with a round number):
select country
from your_table
group by country
having max(case round
when 'Pre Round' then 1
when 'Quater final' then 2
when 'Semi final' then 3
when 'Final' then 4
end) = 1;
If you wanted to find countries that were in the quarters but not semis then you just need to change to = 2, etc.
The second is overkill here, but could be useful to look for more complicated combinations in other types of data:
select country
from your_table
pivot (
count(*) for round in (
'Pre Round' as pre, 'Quater final' as quarter, 'Semi final' as semi, 'Final' as final
)
)
where pre = 1 and quarter = 0 and semi = 0 and final = 0;
Obviously in your example you wouldn't ever have quarter as 0 and then either semi or final as 1 - you can't get to those rounds without playing the quarters; but for other data you might want a mix.
You could use a inner join on subquery for country wih round 're Round' and check for distinct count
select m.Contry
from my_table m
inner join (
select Country
from my_table
where round ='Pre Round'
) t on t.country = m.country
group by m.Country
having count(distinct m.round ) = 1

Redshift: I try to use Union but it returns 3 columns instead of 4. What can I do?

I have to find the streams that took place in a specific country and specific dates (overall_streams) and then for the same country and dates, I have to find the streams for a specific product.
In other words, I am trying to compare how the product did compared to the overall number of streams that took place in this place and time.
For this reason, I tried to use UNION (the subquery I did wouldn't give the right results).
Here is my- simplified- code:
Select age_group, gender, sum(streams) as product_streams
From t1
Where product='A'
And country= 'US'
And date= '1st week of July'
Group by 1,2
Union
Select age_group, gender, sum(streams) as overall_streams
From t1
Where country='US'
And date='1st week of July'
Group by 1,2
Notice the difference in the second query is that I haven't specified a product.
The results I get is 3 columns. The third column is named "product_streams" and it alternates between the product_streams and the overall_streams.
Example:
0-18 f 100
0-18 f 560
0-18 m 45
0-18 m 398
The results are correct, I just want to have 4 columns instead of 3.
Like this:
age_group gender product_streams overall_streams
Any ideas?
I think you want conditional aggregation:
Select age_group, gender,
sum(streams) as overall_streams
sum(case when product = 'A' then streams else 0 end) as product_streams
From t1
Where country = 'US' and
date = '1st week of July'
group by age_group, gender;

SQL Query to create a report of matches played

Recently I have been asked a below SQL query question? Can someone help me with this one. I have a table with three columns - Home Team, Away Team, and Winner Team. Like given below.
H_T A_T W_T
AUS IND IND
ENG AUS ENG
IND AUS AUS
AUS ENG AUS
ENG IND IND
IND ENG IND
Above data needs to be converted in SQL to show the report with below attributes
Team Name, Total Matches Played, Win Count, Draw Count, Loss Count, Points.
To calculate points, these are the formulas for each kind (win/draw/loss)
Win = Win Count * 3
Draw = Draw Count * 1
Loss = Loss Count * 0
Point will be summed up with above three values.
Thanks in advance
Need a little more information as to what defines a draw, this assumes the w_t column contains the value draw instead of a team.
Either way, you can use conditional aggregation to get your desired results. Normally you would have a teams table and join to it, but you can create that with a union and a subquery:
select t.*,
(win_count * 3) + (draw_count) as Points
from (
select t.team,
count(*) Total_Matches_Played,
count(case when t.team = y.w_t then 1 end) Win_Count,
count(case when t.team <> y.w_t then 1 end) Loss_Count,
count(case when y.w_t = 'DRAW' then 1 end) Draw_Count
from (
select h_t as team from yourtable
union select a_t from yourtable
) t join yourtable y on t.team in (y.a_t,y.h_t)
group by t.team
) t

Group multiple result rows in the same row by one column in SQL Server 2008

I am working with SQL Server 2008. I have a temp table which returns the this result:
ID NAME TYPE REGION DATE_HIRED
--------------------------------------------------
75038 GRUPO FOO COMPANY A EUROPE 201512
75038 GRUPO FOO COMPANY A EUROPE 201511
75038 GRUPO FOO COMPANY A EUROPE 201510
I want to get the date of hire of a company and all the information in the same row, and I want the result to be in a format like this:
ID NAME TYPE REGION DATE_HIRED1 DATE_HIRED2 DATE_HIRED3...
75038 GRUPO FOO COMPANY A EUROPE 201512 201511 201510...
The possible dates of hire can be 4 (201512,201511,201510,201509), but a company cannot have a contract in one of those dates?
How to query to get the above result using SQL Server 2008?
I tried using a PIVOT in SQL Server 2008 but I failed.
I suspect the PIVOT operator is what I need (according to this post, anyway), but I can't figure out how to get started, especially when the number of question_id rows in the table can vary. In the above example, it's 5, but in another query the table might be populated with 7 distinct questions.
You can use pivot or conditional aggregation. The key is to get a column for the pivoting -- using row_number():
select id, name, type, region,
max(seqnum = 1 then date_hired end) as date_hired1,
max(seqnum = 2 then date_hired end) as date_hired2,
max(seqnum = 3 then date_hired end) as date_hired3,
max(seqnum = 4 then date_hired end) as date_hired4
from (select t.*,
row_number() over (partition by id order by date_hired) as seqnum
from t
) t
group by id, name, type, region;

How to subtract Total from conditioned sum in SQL

I want to do the following:
1) Find the total rows in a table
2) Find the total rows that meets a certain criteria.
3) Subtract (1) from (2).
Sample table Employees:
EmployeeID Nationality
1 Brazil
2 Korea
3 Germany
4 Brazil
5 Brazil
What I've tried:
SELECT count(EmployeeID) as Total from Employees
UNION
SELECT count(EmployeeID) as Brazilians from Employees
WHERE Nationality = 'Brazil'
Result:
Total
5
3
Row 1 will give me the total Employees. Row 2 will give me the Brazilian Employees.
I used UNION to see if I could subtract row 2 from row 1.
I could do this using CASE and SUM(), but that would require the row_number() function, which I can't use given that I'm using WebSQL. Is there another way to index these rows to be able to subtract?
Is there another approach I could use to solve this seemingly simple problem?
How about counting the rows that don't meet that criteria?
SELECT COUNT(EmployeedID) as non_brazilians
FROM Employees
WHERE Nationality <> 'Brazil';
You can use conditional aggregation:
select count(*) as TotalRows,
sum(case when Nationality = 'Brazil' then 1 else 0 end) as Brazilians,
sum(case when Nationality <> 'Brazil' then 1 else 0 end) as nonBrazilians
from Employee;
This assumes that Nationality is never NULL. If that is possible, the last condition should be:
sum(case when Nationality = 'Brazil' then 0 else 1 end) as nonBrazilians
Try this:
SELECT count(*) AS TotalRows
, (SELECT count(EmployeeID) FROM WHERE Nationality = 'Brazil') as Brazilians
, (count(*) - (SELECT count(EmployeeID) FROM WHERE Nationality = 'Brazil')) AS Subtract1From2
FROM Employee