How to get a ratio of male to female medal winners where a single name can show up multiple times? - postgresql

Say I have the following table:
Name
Sex
Medal
John
M
Gold
John
M
Silver
Chris
M
Bronze
Ana
F
Null
Isobel
F
Bronze
I would like to get the ratio of Male to Female medal winners; in this case, I need to get the number 2 (John and Chris won medals, And won a medal). I don't know how to do this.
What I have is simply listing the number of distinct medal winners, grouped by gender:
SELECT "Sex", COUNT( DISTINCT "Name" ) AS number_of_medal_winners
FROM table
WHERE "Medal" IS NOT NULL
GROUP BY "Sex";
which results in
Sex
number_of_medal_winners
F
1
M
2

Use a case expression to filter what is counted to build your ratio:
SELECT COUNT(CASE WHEN sex = "M" THEN name END)/COUNT(CASE WHEN sex = 'F' THEN name END) as ratio_of_male_medal_winners_to_female
FROM yourtable
WHERE Medal IS NOT NULL

Related

How do I find record above and below based on rank

I have a table called scoreboard and I want to fetch two player above and below based on rank for the arbitrary player.
For example, The given table contains the name and rating.
name
rating
Captain
2100
Ninja
1300
Mango
1760
Steve
1100
Benny
899
Zeus
800
Zeprus
1200
For a given player Zephrus, I need to show below records. Two above him and two below.
rank
name
rating
2
Mango
1760
3
Ninja
1300
4
Zeprus
1200
5
Steve
1100
6
Benny
899
How can I achieve this? I got to know how to find rank using the rank window function in PostgreSQL but not sure how do I achieve two above and two below for a given player effectively.
You can use the rank window function and select the rows with rank within 2 places from the name you're looking for:
with u as
(select *, rank() over(order by rating desc) as r from scoreboard),
v as
(select r from u where name ='Zeprus')
(select r, name, rating from u where abs(r - (select r from v)) <= 2 order by r)
Fiddle

How do I produce a report to show the number of occurrences an employee has been absent from work

I have been asked to generate a report to show the number of occurrences an employee is absent from work sick.
If an employee is absent from work for 3 consecutive days this will be counted as 1 occurrence. If they then return to work and are then absent again for another 2 consecutive days this will be recorded as 2 occurrences.
I need to generate a report to show the number of occurrences an employee is away from work sick within a 6 month period.
I have set out an example below of the data showing an employee's absence records and how i need the report to look.
How data shows in database:
enter image description here
Name Absence Dates
John Smith 01-Sep-19
John Smith 02-Sep-19
John Smith 03-Sep-19
John Smith 10-Sep-19
John Smith 11-Sep-19
How i wish for the report to look:
Name Occurrences
John Smith 2
I would be grateful for any assistance with writing to code to achieve this result.
Not a full answer, as you should really do some of this yourself, however, based on what you have detailed in your quesiton, you could use the approach below to count up any spells of absence, within a 6 month period.
Assumes you would be compiling this using SQL Server
declare #absences table (empid nvarchar(10), [abs date] date, [ret date] date);
declare #staff table ([empid] int, [name1] nvarchar(50), [name2] nvarchar(50), [surname] nvarchar(50));
-- put some test values in the staff table to work with
insert into #staff
values
(1, 'John', 'Lewis', 'Smith'), -- using a unique ID here, in any good system this should be an incremental number for each new staff member added to the table
(2, 'James', 'Thomas', 'Brown')
-- put some test values in the absences table to work with
insert into #absences
values
(1, '2019-07-01', '2019-07-04'), -- userid, absence date & return date
(1, '2019-08-04', '2019-08-06'),
(2, '2019-07-02', '2019-07-05'),
(2, '2019-08-05', '2019-08-07')
select count(*) spellsoff, empid, name1, name2, surname, [days absent]
from
(
select
s.empid,
s.name1,
s.name2,
s.surname,
a.[abs date],
a.[ret date],
datediff(d,a.[abs date], a.[ret date]) [days absent]
from #staff s
left join #absences a
on s.empid = a.empid
where [abs date] >= DATEADD(M,-6,GETDATE()) -- pull back those employeess that have been absent in the last 6 months from today's date
)doff
group by empid, name1, name2, surname, [days absent]
Gives you the following breakdown:
spellsoff empid name1 name2 surname days absent
1 1 John Lewis Smith 2
1 1 John Lewis Smith 3
1 2 James Thomas Brown 2
1 2 James Thomas Brown 3

Select a specific row from a table with duplicated entries based on one field

I have a table which holds data in the following format, however I would like to be able to create a query that checks whether the reference number is duplicated and only return the entry with the latest date_issued.
ref_no name gender place date_issued
xgb/358632/p John Smith M London 02.08.2016
Xgb/358632/p John Smith M London 14.06.2017
Rtu/638932/k Jane Doe F Birmingham 04.09.2017
The result from the query should be;
ref_no name gender place date_issued
Xgb/358632/p John Smith M London 14.06.2017
Rtu/638932/k Jane Doe F Birmingham 04.09.2017
Is there a fairly straightforward solution for this?
assuming the date column is type date or timestamp
select distinct on(ref_no) * from tablename order by refno,date desc;
this works beacuse distinct on supresses rows with duplicates of the expression in parenthese.

How to calculate market share in tableau

I have a data set for 10 countries. Each country has more than 8 products and my company has 3 products A,B,C which are sold in each of the country.
So Now, I want to calculate the market share for my products country wise.
for E.g. If total sale for 8 products in country 1 is 100 and sale for products A+B+C is 35, then market share of my company in country1 is 35/100= 35%
.
Please help !
It depends a bit on what you want to do with that afterwards, if you are just interested in the number, do the following:
Create a calculated field TotalSalesPerCountry with {fixed [country]: sum([Sales])} (calculates the total sales per country)
Create a calculated field CompanySalesPerCountry with {fixed [country]: sum(IIF([Product] = 'A' OR [Product] = 'B' OR [Product] = 'C',[Sales],0))} (calculates the total sum per country where [PRODUCT] = A, B or C)
Create a calculated field MarketShare with AVG([CompanySalesPerCountry]) / AVG([TotalSalesPerCountry])
Change the Properties for the last field to 'Percent', drag [Country] to rows and [MarketShare] to columns

How to calculate average number and give subquery label

I have two table "book" and "authorCollection". Because a book may have multi-authors, I hope to get the average number of authors in table "book" which published after year 2000(inclusive).
For example:
Table Book:
key year
1 2000
2 2001
3 2002
4 1999
Table authorCollection:
key author
1 Tom
1 John
1 Alex
1 Mary
2 Alex
3 Tony
4 Mary
The result should be (4 + 1 + 1) / 3 = 2;(key 4 publish before year 2000).
I write the following query statement, but not right, I need to get the number of result in subquery, but cannot give it a label "b", How can i solve this problem? And get the average number of author? I still confused about "COUNT(*) as count" meaning....Thanks.
SELECT COUNT(*) as count, b.COUNT(*) AS total
FROM A
WHERE key IN (SELECT key
FROM Book
WHERE year >= 2000
) b
GROUP BY key;
First, count number of authors for a key in a subquery. Next, aggregate needed values:
select avg(coalesce(ct, 0))
from book b
left join (
select key, count(*) ct
from authorcollection
group by 1
) a
using (key)
where year >= 2000;
A sample as well as handling 'divide by zero' error:
select case when count(distinct book.key)=0
then null
else count(authorCollection.key is not null)/count(distinct book.key)
end as avg_after_2000
from book
left join authorCollection on(book.key=authorCollection.key)
where book.year >= 2000