Top percentage of records in SQL Server - sql-server-2014

I have a table with 3000 records.
PRODUCT
-----------
PID
QTY
EMPID
When I try to get 5% of records for each employee ID, It is returning 5% of total records instead of 5% for each employee.
SELECT TOP 5 PERCENT EMPID,QTY,PID FROM PRODUCT
GROUP BY EMPID,QTY,PID
How do I get 5% of records for each employee rather than 5% of the total.
Appreciate if you can helo

SQL Server might have a better way to do this, but one simple option using COUNT as analytic function would be:
WITH cte AS (
SELECT *,
COUNT(*) OVER (PARTITION BY EMPID ORDER BY QTY DESC) /
COUNT(*) OVER (PARTITION BY EMPID) AS cnt_pct
FROM PRODUCT
)
SELECT EMPID, QTY, PID
FROM cte
WHERE cnt_pct <= 0.05;
This return only records for each employee which corresponded to the top 5% as ordered descending by quantity. Note that your original query probably should have some sort of ORDER BY clause, without which TOP does not make much sense.

Related

Calculating Value Count and Percentage

I have a table
Currently Enrolled
The table is basically to get an idea of how many supporters, undecided, and opposition they were. Then once I get the count I wanted to then do another calculation to find out what that percentage was.
Essentially what I want to be able to do is:
Count the total number of supporters:
SELECT count(*) AS 'SUPPORTERS' FROM CURRENTLY ENROLLED WHERE
status = 'Supporter'
results were 13
Count the total number of opposition:
SELECT count(*) AS 'OPPOSITION' FROM CURRENTLY ENROLLED WHERE value = 'Opposition'
results were 11
Count the total number of undecided persons using a similar statement:
SELECT count(*) AS 'UNDECIDED' FROM CURRENTLY ENROLLED WHERE value = 'Undecided'
results were 5
So with the count, I can see that they're 29 total individuals. I wanted to be able to get the percentage of each of them separately. Something like
13/29 * 100 = 44%
11/29 * 100 = 37%
5/29 * 100 = 17%
However, I am lost on how to write this query.
Hope I am making this clear as to the intentions.
Use a CTE for the total and group by status for the percentage:
with cte as (select count(*) as cnt from `currently enrolled`)
select status, sum(100)/cnt
from `currently enrolled`, cte
group by 1

Sum Distinct Duplicated Values

I have a dataset as below:
customer buy profit
a laptop 350
a mobile 350
b laptop case 50
c laptop 200
c mouse 200
It does not matter how many rows the customer has, the profit is already stated in the row (it's already an accumulative sum). For example, the profit of customer a is 350 and the profit of customer c is 200.
I would like to sum uniquely the profit for all the customers so the desire output should be 350 + 50 + 200 = 600. However, I need to execute this in one line of code (without doing subquery, nested query or write in a separate CTE).
I tried with Partition By but cannot combine MAX and SUM together. I also tried SUM (DISTINCT) but it does not work either
MAX(profit) OVER (PARTITION BY customer)
If anyone could give me a hint on an approach to tackle this, it would be highly appreciated.
You really should use a subquery here:
SELECT SUM(profit) AS total_profit
FROM (SELECT DISTINCT customer, profit FROM yourTable) t;
By the way, your table design should probably change such that you are not storing the redundant profit per customer across many different records.
You can combine SUM() window function with MAX() aggregate function:
SELECT DISTINCT SUM(MAX(profit)) OVER () total
FROM tablename
GROUP BY customer;
See the demo.
Select sum(distinct profit) as sum from Table
You can select max profit of each customer like this:
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
Then you can summarise the result in your code or even in the query as nested queries:
SELECT SUM(max_profit) FROM (
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
) AS temptable

SQL: How to select year and month when customer's turnover was the biggest?

I need to List top 10 customers by average monthly transactions amount turnover, in
additional column indicating the year and month with highest monthly turnover of the customer.
I made the first part - list top 10 customers by average monthly transactions amount turnover.
Select column1, AVG(Case when when column1="x" then column2
when column1="y" then column2
when column1="z" then column2
when column1="q" then column2 End)/12 [AVG]
from table1
Group by column1
Order by AVG DESC;
How to make the second part of the task - in
additional column indicating the year and month with highest monthly turnover of the customer?
This sounds like aggregation and window functions. Date functions are notoriously database-dependent, but the idea is:
select ymc.*
from (select year(r_date) as yyyy, month(r_date) as mm, c_id, sum(amount) as amount,
row_number() over (partition by c_id order by sum(amount) desc) as seqnum
from t
group by year(r_date), month(r_date), c_id
) ymc
where seqnum = 1;
Not all databases support year() and month() but all have similar functionality. So you may need to modify for what your database uses.
Use below query, below query in for Oracle, tag your database so that can provide appropriate query.
select c_id, to_char(r_date, 'MM'), to_char(r_date, 'YYYY'), max(amount)
group by c_id, to_char(r_date, 'MM'), to_char(r_date, 'YYYY');

SQL query to find Sum of Amount from table Totals for all IDs for only Maximum Amounts

Totals table is
ID|Amount
1|10
1|20
2|30
2|40
3|50
4|60
5|70
5|80
Tried below SQL query to find sum of Amount from table Totals for all IDs for only Maximum Amounts:
select SUM(Amount) from Totals
where ID in (select Max(ID) from Totals
group by ID
order by ID desc);
Use a subquery that gets the maximum amount for each ID, then sum it.
SELECT SUM(amount) as totalMax
FROM (
SELECT MAX(amount) AS amount
FROM Totals
GROUP BY ID
) AS x

Combining Two Select Sum Statements Into One

I have two statements within my table which work fine individually like this:
SELECT fee_earner, (SUM(fe_fees)) AS Total
FROM fees
GROUP BY fee_earner
order by Total desc;
SELECT supervisor, (SUM(sv_fees)) AS Total
FROM fees
GROUP BY supervisor
order by Total desc;
But there are some cases where the fee_earner and supervisor fields have the same person as the data, is there a way to combine these two statements into one to get the overall totals?
You can use union all for this:
SELECT person, sum(fe_fees) as fe_fees, sum(sv_fees) as sv_fees,
(sum(fe_fees) + sum(sv_fees)) as total
FROM ((select fee_earner as person, fe_fees as fe_fees, 0 as sv_fees, 'earner' as which
from fees
) union all
(select supervisor as person, 0 as fe_fees, sv_fees as sv_fees, 'supervisor' as which
from fees
)
) t
GROUP BY person
order by Total desc;
select
fee_earner, SUM(fe_fees) as total, SUM(sv_fees) as total2,
SUM(fe_fees) + SUM(sv_fees) as wholeTotal
from
fees
group by
fee_earner, supervisor
order by
Total desc;