Custom row cell in SQL - sql

So I'm looking to use a custom row cell to label my data.
Basketball
Baseball
Golf
Cost
1
0
0
$50
0
1
0
$75
1
0
1
$150
0
1
1
$225
The table I have is above. What I'm trying to do is below:
OUTPUT:
Sport
Cost
Basketball
200
Baseball
300
Golf
375
I can get the sum of each sport but I'm having trouble making an alias for each sport on the output table (The first column)
How would I go about that? I've done an alias for a column header, but never for a row cell.
Thanks in advance!

select game
,sum(cost*flg) as cost
from t
cross join lateral (
values
(basketball, 'basketball')
,(baseball, 'baseball')
,(golf, 'golf')
) t2(flg, game)
group by game
game
cost
golf
375
baseball
300
basketball
200
Fiddle

Use a UNION with different WHERE conditions:
select sport, sum(cost)
from
(
select 'Basketball' as sport, cost
from the_table
where basketball = 1
union all
select 'Baseball', cost
from the_table
where baseball = 1
union all
select 'Golf', cost
from the_table
where golf = 1
) t
group by sport;

Related

How to group by Max?

I'm having some trouble with a statement,
I have a table like this
Player Number
Sport
Date
1
soccer
4/1
4
basketball
4/2
2
basketball
4/3
3
soccer
4/1
1
baseball
4/2
4
basketball
4/3
5
soccer
4/1
3
baseball
4/2
5
soccer
4/2
2
basketball
4/3
1
soccer
4/4
2
baseball
4/5
3
soccer
4/4
4
soccer
4/5
5
soccer
4/3
5
basketball
4/5
I'm trying to write a query that will give me a table that will group together the players by their most played sport so the end result will look like this:
Sport
# of Players Who played the sport the most
Baseball
2
Basketball
1
Soccer
2
I was able to write a statement that shows the number of times each player played a a specific sport but am having trouble getting the table to only select the rows with the highest number of plays and arranging it to be grouped by each sport.
Select distinct PLAYER_NUMBER, SPORT, Max(GAMES_PLAYED) as GAMES_PLAYED
FROM #temp
Group By SPORT, PLAYER_NUMER
order by GAMES_PLAYED desc
I don't think your desired results match your sample data?
Anyway start with a query to get the number of plays per player, and use the row_number window function to determine which sport was played the most for each player (note what do you want to do in the case of a tie?). Then in the next query only use the sport with the most plays per player and group by sport.
with cte as (
select *
-- For each player get the sport with the most plays
, row_number() over (partition by Player order by count(*) desc) rn
from #temp
group by Player, Sport
)
select Sport
, count(*) [# of Players Who played the sport the most]
from cte
where rn = 1
group by Sport
order by Sport;
Returns:
Sport
# of Players Who played the sport the most
basketball
2
soccer
3
The following related query allows one to confirm the results shown above:
with cte as (
select *
, count(*) num
, row_number() over (partition by Player order by count(*) desc) rn
from #temp
group by Player, Sport
)
select Player, Sport, num
from cte
order by Player, num desc;
Which shows for each player which sport was played the most i.e. its the first row for each player, and note baseball never shows up as the most played sport! The actual results are calculated using every rn=1 because that is the sport most played per player.
Player
Sport
num
rn
1
soccer
2
1
1
baseball
1
2
2
basketball
2
1
2
baseball
1
2
3
soccer
2
1
3
baseball
1
2
4
basketball
2
1
4
soccer
1
2
5
soccer
3
1
5
basketball
1
2
If I understand you right, you might also get this by subqueries
select s.sport,
count(distinct s.playdate) as times_played,
(select max(t.players) from (
select count(distinct s2.player) as players
from sports s2
where s2.sport = s.sport
group by s2.sport, s2.playdate
) t
) as nbr_players
from sports s
group by s.sport
this gets me
sport
times_played
nbr_players
baseball
2
2
basketball
3
2
soccer
5
3
DBFiddle here

Equivalent of excel COUNTIFS

I am trying to get a COUNTIFS from excel type of result
Here is the products table:
Name Product
john car
john football
john image
max food
max tv
max laptop
max image
max image
max image
alex tv
alex laptop
alex image
alex cake
alex cake
alex cake
alex cake
alex car
The output should be:
Name Product Number of products per person Number of products of the same type
john car 1 2
john football1 1
john image 1 5
max food 1 1
max tv 1 2
max laptop 1 2
max image 3 5
alex tv 1 2
alex laptop 1 2
alex image 1 5
alex cake 4 4
alex car 1 2
Number of products per person is count of products by name by product
and Number of products of the same type is based on the total count by product
for example image is repeated 3 times for max so in col C the answer is 3 but it there 5 times in the table so answer in col D is 5
I tried but not getting the correct answer:
SELECT
name,
product,
COUNT(*),
COUNT(*) OVER (PARTITION BY product),
from products
GROUP BY 1,2
ORDER BY 1
You are quite close. You need to sum the COUNT(*). You can do this directly in the aggregation query:
SELECT name, product,
COUNT(*),
SUM(COUNT(*)) OVER (PARTITION BY product)
FROM products
GROUP BY 1, 2
ORDER BY 1
#standardSQL
SELECT name, product, product_per_person,
SUM(product_per_person) OVER(PARTITION BY product) product_total
FROM (
SELECT
name,
product,
COUNT(*) product_per_person
FROM `project.dataset.products`
GROUP BY 1,2
)
ORDER BY 1
if to apply to your sample data - result should be
Row name product product_per_person product_total
1 alex cake 4 4
2 alex car 1 2
3 alex image 1 5
4 alex laptop 1 2
5 alex tv 1 2
6 john car 1 2
7 john football 1 1
8 john image 1 5
9 max food 1 1
10 max image 3 5
11 max laptop 1 2
12 max tv 1 2
use group by name and product
SELECT name,
product,
COUNT(*),
COUNT(*) OVER (partition by product)
from products
GROUP BY name,product
ORDER BY 1

SQLite percentages with small values

So I have this table of subscribers of users and the country they are in.
UserID | Name | Country
-------+-------------------+------------
1 | Zaphod Beeblebrox | UK
2 | Arthur Dent | UK
3 | Gene Kelly | USA
4 | Nat King Cole | USA
I need to produce a list of all the users by percentage from each of the countries. I also need all the smaller member countries (under 1%) to be collapsed into an "OTHERS" category.
I can accomplish a simple "top x" of members trivially with a
SELECT COUNTRY, COUNT(*) AS POPULATION FROM SUBSCRIBERS GROUP BY COUNTRY ORDER BY POPULATION DESC LIMIT 10
and can generate the percentages by PHP server side code, but I don't quite know how to:
Do all of it in SQL including percentage calculations directly in the result
Club all under 1% members into a single OTHERS category.
So I need something like this:
Country | Population
--------+-----------
USA | 25.4%
Brazil | 12%
UK | 5%
OTHERS | 65%
Appreciate the help!
Here is query for this, I used a subquery to count the total number of rows and then used that to get the percentage value for each. The 'Others' category was generated in a separate query. Rows are sorted by descending population with the Others row last.
SELECT * FROM
(SELECT country , ROUND((100.0*COUNT(*)/count_all),1) ||'%' AS population
FROM (SELECT count(*) count_all FROM subscribers) AS sq,
subscribers s
WHERE (SELECT 100*count(*)/count_all
FROM subscribers s2
WHERE s2.country = s.country) > 1
GROUP BY country
ORDER BY population DESC)
UNION ALL
SELECT 'OTHERS', IFNULL(ROUND(100.0*COUNT(*)/count_all,1),0.0) ||'%' AS population
FROM (SELECT count(*) count_all FROM subscribers) AS sq,
subscribers s
WHERE (SELECT 100*count(*)/count_all
FROM subscribers s2
WHERE s2.country = s.country) <= 1
Ok I think I might have found a way to do this that's a hell of a lot quicker on execution speed:
SELECT territory,
Round(Sum(percentage), 3) AS Population
FROM (SELECT
Round((Count(*)*100.0)/(SELECT Count(*) FROM subscribers),3) AS Percentage,
CASE
WHEN ((Count(*)*100.0)/(SELECT Count(*) FROM subscribers)) > 2 THEN
country
ELSE 'Other'
END AS Territory
FROM subscribers
GROUP BY country
ORDER BY percentage DESC)
GROUP BY territory
ORDER BY population DESC;

Reconciliation Automation Query

I have one database and time to time i change some part of query as per requirement.
i want to keep record of results of both before and after result of these queries in one table and want to show queries which generate difference.
For Example,
Consider following table
emp_id country salary
---------------------
1 usa 1000
2 uk 2500
3 uk 1200
4 usa 3500
5 usa 4000
6 uk 1100
Now, my before query is :
Before Query:
select count(emp_id) as count,country from table where salary>2000 group by country;
Before Result:
count country
2 usa
1 uk
After Query:
select count(emp_id) as count,country from table where salary<2000 group by country;
After Query Result:
count country
2 uk
1 usa
My Final Result or Table I want is:
column 1 | column 2 | column 3 | column 4 |
2 usa 2 uk
1 uk 1 usa
...... but if query results are same than it shouldn't show in this table.
Thanks in advance.
I believe that you can use the same approach as here.
select t1.*, t2.* -- if you need specific columns without rn than you have to list them here
from
(
select t.*, row_number() over (order by count) rn
from
(
-- query #1
select count(emp_id) as count,country from table where salary>2000 group by country;
) t
) t1
full join
(
select t.*, row_number() over (order by count) rn
from
(
-- query #2
select count(emp_id) as count,country from table where salary<2000 group by country;
) t
) t2 on t1.rn = t2.rn

Hive sql: count and avg

I'm recently trying to learn Hive and i have a problem with a sql consult.
I have a json file with some information. I want to get the average for each register. Better in example:
country times
USA 1
USA 1
USA 1
ES 1
ES 1
ENG 1
FR 1
then with next consult:
select country, count(*) from data;
I obtain:
country times
USA 3
ES 2
ENG 1
FR 1
then i should get next out:
country avg
USA 0,42 (3/7)
ES 0,28 (2/7)
ENG 0,14 (1/7)
FR 0,14 (1/7)
I don't know how i can obtain this out from the first table.
I tried:
select t1.country, avg(t1.tm),
from (
select country,count(*)as tm from data where not country is null group by country
) t1
group by t1.country;
but my out is wrong.
Thanks for help!! BR.
Divide the each group count by total count to get the result. Use Sub-Query to find the total number of records in your table
Try this
select t1.country, count(*)/IFNULL((select cast(count(*) as float) from data),0)
from data
group by t1.country;