Keep the aggregated column constant in SQL Server? - sql

I am trying to do count of client locations that are count > 1, which seems to work fine as indicated in the first query.
select clientID,count(clientlocations)clientcount
from db.schema.table
group by clientid
having count(clientid) > 1
clientid clientcount
1 5
2 7
3 8
But in order for me to join with the revenue I need to bring in the revenueid which fragments the clientcount.
select reveneueid,clientID,
count(clientlocations)clientcount
from db.schema.table
group by revenueid,clientid
having count(clientid) > 1
revenueid clientid clientcount
5000 1 4
6144 1 1
4651 2 3
4785 2 1
8745 2 3
7869 3 5
4963 3 3
A client can have multiple `revenueid'.
I want to have constant count of the client likewise below.
Requested:
select reveneueid,clientID,
count(clientlocations)clientcount
from db.schema.table
group by revenueid,clientid
having count(clientid) > 1
revenueid clientid clientcount
5000 1 5
6144 1 5
4651 2 7
4785 2 7
8745 2 7
7869 3 8
4963 3 8
I am using SQL Server 2016.

You could use windowed SUM per clientid
select reveneueid,clientID,
SUM(count(clientlocations)) OVER(PARITION BY clientid) AS clientcount
from db.schema.table
group by revenueid,clientid
having count(clientid) > 1

Related

SQL Query to get multiple resultant on single column

I have a table that looks something like this:
id name status
2 a 1
2 a 2
2 a 3
2 a 2
2 a 1
3 b 2
3 b 1
3 b 2
3 b 1
and the resultant i want is:
id name total count count(status3) count(status2) count(status1)
2 a 5 1 2 2
3 b 4 0 2 2
please help me get this result somehow, i can just get id, name or one of them at a time, don't know how to put a clause to get this table at once.
Here's a simple solution using group by and case when.
select id
,count(*) as 'total count'
,count(case status when 3 then 1 end) as 'count(status1)'
,count(case status when 2 then 1 end) as 'count(status3)'
,count(case status when 1 then 1 end) as 'count(status2)'
from t
group by id
id
total count
count(status3)
count(status2)
count(status1)
2
5
1
2
2
3
4
0
2
2
Fiddle
Here's a way to solve it using pivot.
select *
from (select status,id, count(*) over (partition by id) as "total count" from t) tmp
pivot (count(status) for status in ([1],[2],[3])) pvt
d
total count
1
2
3
3
4
2
2
0
2
5
2
2
1
Fiddle

Sum if same ID1 and ID2 - only once - SQL

I have the following data on SQL
EntryID
PersonID
JobID
JobSalary
1
1
1
270000
2
1
2
500000
3
2
3
320000
4
3
4
180000
5
2
3
320000
6
1
3
85000
7
1
1
270000
8
1
2
500000
9
2
3
320000
10
3
4
180000
For each entry, I want to have a column that calculates the total salary (of all jobs) of the specific person.
The tricky part is that multiple entries can refer to the same person and/or the same job, but I only want to sum up each job for each person once.
The output would be:
EntryID
PersonID
JobID
JobSalary
PersonTotalSalaryAllJobs
1
1
1
270000
855000
2
1
2
500000
855000
3
2
3
320000
320000
4
3
4
180000
180000
5
2
3
320000
320000
6
1
3
85000
855000
7
1
1
270000
855000
8
1
2
500000
855000
9
2
3
320000
320000
10
3
4
180000
180000
Any ideas on how to do this?
Thanks!
To get what you want you can use a query like this
SELECT
s.*,
pjts.total_salary
FROM salary s
LEFT JOIN (
SELECT
*,
SUM(jobsalary) OVER (PARTITION BY personid) AS total_salary
FROM (
SELECT DISTINCT
personid,
jobid,
jobsalary
FROM salary
) pjs
) pjts ON s.personid = pjts.personid AND s.jobid = pjts.jobid
You can check a working demo here
Or even simplier using only one subquery like this
SELECT
s.*,
pjts.total_salary
FROM salary s
LEFT JOIN (
SELECT
personid,
jobid,
SUM(jobsalary) OVER (PARTITION BY personid) AS total_salary
FROM salary
GROUP BY personid, jobid, jobsalary
) pjts ON s.personid = pjts.personid AND s.jobid = pjts.jobid
You can check a working demo here

How to Subtotal Value with MAX

1.I have data as follows (just a subset - there are 20K records)
sku,id
1 1
1 2
1 2
1 2
1 3
1 4
1 1
1 2
1 3
1 4
1 4
1 4
1 5
1 6
1 6
2 1
2 1
2 2
2 3
2 3
2 3
2 4
2 4
2 5
2 5
2 6
2 7
2 1
2 2
2 3
The above values translate to
1 = 4 records
1 = 6 records
2 = 7 records
2 = 3 records
The MAX would just give me 6 for one and 7 for 2
The actual total is 1 = 10 and 2 = 10
How do I sum up to get the correct values?
You can use order by and some way of limiting rows. In standard SQL this would be:
select t.*
from t
order by id desc
fetch first 2 rows only;
However, some databases might use limit or select top or some other method.
No handling of ties here. Thousands of other questions handle this topic.
select sku, id
from (
select *, row_number() over (order by id desc) rn
from T
) t
where rn <= 2
order by rn desc;

using sql join on three tables

I have 3 tables which maintains stock entries for each products/items. These three tables like below :
Table : ItemStock (to maintain remaining stock of each item)
Id ItemId OpgQty BranchID CurrentStock
1 7 0 1 8
2 7 0 2 3
3 6 0 1 2
4 6 0 2 0
Table : ItemPurchase (StockIn)
Id ItemId Qty BranchID
1 7 5 1
2 7 4 2
3 7 6 1
4 7 2 2
5 6 4 1
6 6 2 2
7 6 2 1
Table : ItemSale (StockOut)
Id ItemId Qty BranchID
1 7 2 1
2 7 3 2
3 7 1 1
4 6 4 1
5 6 2 2
Desired Output (based on sql queries)
I want to have result like below : (part of report)
Id ItemId OpgQty BranchId StockIn StockOut CurrentStock
1 7 0 1 11 3 8
2 7 0 2 6 3 3
3 6 0 1 6 4 2
4 6 0 2 2 2 0
I was trying to get the desired result but was not able to do so. Please help!!!
try this;
select
m.Id,
m.ItemId,
m.OpgQty,
m.BranchID,
si.StockIn,
m.CurrentStock-si.StockIn StockOut,
m.CurrentStock
from
ItemStock m
inner join
(
select
ItemId,BranchId,sum(Qty) as StockIn
from
ItemPurchase
group by ItemId,BranchId
) si on si.ItemId=m.ItemId and si.BranchId=m.BranchId
A very simple query that gives the desired result is :
select *,
(select sum(Qty)
from ItemPurchase
where ItemPurchase.ItemId = ItemStock.ItemId and
ItemPurchase.BranchId = ItemStock.BranchId) as StockIn,
(select sum(Qty)
from ItemSale
where ItemSale.ItemId = ItemStock.ItemId and
ItemSale.BranchId = ItemStock.BranchId) as StockOut
from ItemStock
Two subqueries with group by and aggregation will get what you want.
select
s.*,
coalesce([ip].StockIn, 0) as StockIn, -- In case of no records in ItemPurchase or ItemSale, coalesce is neccessary.
coalesce([is].StockOut, 0) as StockOut
from ItemStock s
left join (
select sum(Qty) as StockIn, ItemId, BranchId
from ItemPurchase
group by ItemId, BranchId
) [ip] on s.ItemId = [ip].ItemId and s.BranchId = [ip].BranchId
left join (
select sum(Qty) as StockOut, ItemId, BranchId
from ItemSale
group by ItemId, BranchId
) [is] on s.ItemId = [is].ItemId and s.BranchId = [is].BranchId
See demo in sqlfiddle.
Please
Try This ... I hope you consider this too.

SQL Group by: how to get % of records over a certain score

I have a SQL table similar to the below. How do I do a SQL Group By where I can get the percentage of calls rated 9 or above per step?
So basically I want to group by StepID and next to it I want to show the % of calls that has its rating over 9.
CallID StepID Rating
1 1 8
1 2 6
1 3 9
2 1 10
2 2 10
2 3 5
3 1 7
3 2 5
3 3 8
In this case, next to StepID = 1, would display 33% (1 out of 3 calls for stepID 1 is over 9).
select
StepID,
cast(sum(case when Rating > 9 then 100.0 else 0 end)
/count(*) as decimal(5,2)) pct
from yourtable
group by StepID