SQL Query to return the sum of balances from 1 or more rows from the same table - sql

My first post on stackoverflow - I hope you can assist this newbie please!
I have a requirement to return the sum of Leave Balances from 1 or more rows in the same table in SQL Server 2012. The result set must be grouped by EmployeeID and BalanceStartDate. There are instances where an employee has multiple LeaveType's, and there are instances where employees only has one leave type.
If only one LeaveType exists for the BalanceStartDate and Employee, then return the LeaveBalance. If multiple exist, sum the LeaveBalance across the LeaveType and return 1 result.
My source data on the table is as follows:
EmployeeID BalanceStartDate LeaveCategory LeaveType LeaveBalance
---------- ---------------- ------------- --------- ------------
1 01-JAN-2016 ANNUAL MANDATORY 2
1 01-JAN-2016 ANNUAL NON-MAN 3
1 01-JAN-2015 ANNUAL MANDATORY 5
1 01-JAN-2015 ANNUAL NON-MAN 2
2 01-JAN-2016 ANNUAL MANDATORY 6
2 01-JAN-2015 ANNUAL MANDATORY 3
2 01-JAN-2014 ANNUAL MANDATORY 1
2 01-JAN-2014 ANNUAL NON-MAN 1
My expected result set is:
EmployeeID BalanceStartDate LeaveCategory Sum
---------- ---------------- ------------- ---
1 01-JAN-2016 ANNUAL 5
1 01-JAN-2015 ANNUAL 7
2 01-JAN-2016 ANNUAL 6
2 01-JAN-2015 ANNUAL 3
2 01-JAN-2014 ANNUAL 2
So for each "year", we should have a unique row summing up the balance across the LeaveTypes (if more than one exists). If there is only 1 LeaveType, then only return the Leave Balance.
I wrote the following (which is almost there), but it is excluding rows where only 1 LeaveType exists, and is still returning 2 rows for a single year:
select A.LeaveBalance + B.LeaveBalance as 'Sum', A.EmployeeID
From
Table A
Inner Join Table B On A.EmployeeID = B.EmployeeID
AND A.LeaveCategory = 'ANNUAL'
AND A.LeaveCategory = B.LeaveCategory
AND A.BalanceStartDate = '01-JAN-2016'
AND A.BalanceStartDate = B.BalanceStartDate
AND A.EmployeeID = '12345'
AND A.LeaveType <> B.LeaveType
I hope this is enough Info?
Any assistance would be greatly appreciated. Please excuse my newbie code!

select
EMPLOYEEID
,BALANCESTARTDATE
,LEAVECATEGORY
,SUM( LEAVEBALANCE ) as sum
from
EMPLOYEES
group by
EMPLOYEEID
,BALANCESTARTDATE
,LEAVECATEGORY
order by
EMPLOYEEID
,BALANCESTARTDATE desc;
It will give result as you expected.

You should use SUM function.
Try this:
SELECT EmployeeID, BalanceStartDate, LeaveCategory, LeaveType, SUM(LeaveBalance) As SumOfLeaves
FROM YourTable
GROUP BY EmployeeID, BalanceStartDate, LeaveCategory, LeaveType

Try this,
SELECT
A.EmployeeID,
A.LeaveCategory,
A.BalanceStartDate,
SUM(A.LeaveBalance) AS TotalLeave
FROM
Table A
WHERE A.LeaveCategory = 'ANNUAL'
AND A.EmployeeID = '12345'
GROUP BY
A.EmployeeID,
A.LeaveCategory,
A.BalanceStartDate

Related

Populate empty values from another table

Let us say that I have two SQL tables
Employee Recognition Table
Employee Id
Reward Date
Coupon
1
1/1/2020
null
1
1/2/2020
null
1
1/3/2020
null
2
2/1/2020
null
2
2/2/2020
null
3
2/2/2020
null
Coupons
Employee Id
Coupon
1
COUPON1
1
COUPON2
1
COUPON3
2
COUPON4
What I want to do is allot coupons to all the employee uniquely, example
employee 1 has three coupons so they should be allotted
employee 2 just has 1 coupon so 1 should get allotted
employee 3 has none
So the output should be something like
Employee Recognition Table Updated
Employee Id
Reward Date
Coupon
1
1/1/2020
COUPON1
1
1/2/2020
COUPON2
1
1/3/2020
COUPON3
2
2/1/2020
COUPON4
2
2/2/2020
null
3
2/2/2020
null
Also the table contains a lot of records both tables above 100k records so wondering what a performant query can look like. I have thought about using lateral joins but the speed seems to be the issue there.
Use below
select * except(pos)
from (
select Employee_Id, Reward_Date,
row_number() over(partition by Employee_Id order by Reward_Date) pos
from recognitions
)
left join (
select Employee_Id, Coupon,
row_number() over(partition by Employee_Id order by Coupon) pos
from coupons
)
using (Employee_Id, pos)
-- order by Employee_Id, Reward_Date
if applied to sample data in your question - output is

Count values separately until certain amount of duplicates SQL

I need a Statement that selects all patients and the amount of their appointments and when there are 3 or more appointments that are taking place on the same date they should be counted as one appointment
That is what my Statement looks so far
SELECT PATSuchname, Count(DISTINCT AKTDATUM) AS AKTAnz
FROM tblAktivitaeten
LEFT OUTER JOIN tblPatienten ON (tblPatienten.PATID=tblAktivitaeten.PATID)
WHERE (AKTDeleted<>'J' OR AKTDeleted IS Null)
GROUP BY PATSuchname
ORDER BY AKTAnz DESC
The result should look like this
PATSuchname Appointments
----------------------------------------
Joey Patner 13
Billy Jean 15
Example Name 13
As you can see Joey Patner has 13 Appointments, in the real table though he has 15 appointments but three of them have the same Date and because of that they are only counted as 1
So how can i write a Statement that does exactly that?
(I am new to Stack Overflow, sorry if the format I use is wrong and tell me if it is.
In the table it looks like this.
tblPatienten
----------
PATSuchname PATID
------------------------
Joey Patner 1
Billy Jean 2
Example Name 3
tblAktivitaeten
----------
AKTDatum PATID AKTID
-----------------------------------------
08.02.2021 1 1000 ----
08.02.2021 1 1001 ---- So these 3 should counted as 1
08.02.2021 1 1002 ----
09.05.2021 1 1003
09.07.2021 2 1004 -- these 2 shouldn't be counted as 1
09.07.2021 2 1005 --
Two GROUP BY should do it:
SELECT
x.PATID, PATSuchname, SUM(ApptCount)
FROM (
SELECT
PATID, AKTDatum, CASE WHEN COUNT(*) < 3 THEN COUNT(*) ELSE 1 END AS ApptCount
FROM tblAktivitaeten
GROUP BY
PATID, AKTDatum
) AS x
LEFT JOIN tblPatienten ON tblPatienten.PATID = x.PATID
GROUP BY
x.PATID, PATSuchname

Count the number of transactions per month for an individual group by date Hive

I have a table of customer transactions where each item purchased by a customer is stored as one row. So, for a single transaction there can be multiple rows in the table. I have another col called visit_date.
There is a category column called cal_month_nbr which ranges from 1 to 12 based on which month transaction occurred.
The data looks like below
Id visit_date Cal_month_nbr
---- ------ ------
1 01/01/2020 1
1 01/02/2020 1
1 01/01/2020 1
2 02/01/2020 2
1 02/01/2020 2
1 03/01/2020 3
3 03/01/2020 3
first
I want to know how many times customer visits per month using their visit_date
i.e i want below output
id cal_month_nbr visit_per_month
--- --------- ----
1 1 2
1 2 1
1 3 1
2 2 1
3 3 1
and what is the avg frequency of visit per ids
ie.
id Avg_freq_per_month
---- -------------
1 1.33
2 1
3 1
I tried with below query but it counts each item as one transaction
select avg(count_e) as num_visits_per_month,individual_id
from
(
select r.individual_id, cal_month_nbr, count(*) as count_e
from
ww_customer_dl_secure.cust_scan
GROUP by
r.individual_id, cal_month_nbr
order by count_e desc
) as t
group by individual_id
I would appreciate any help, guidance or suggestions
You can divide the total visits by the number of months:
select individual_id,
count(*) / count(distinct cal_month_nbr)
from ww_customer_dl_secure.cust_scan c
group by individual_id;
If you want the average number of days per month, then:
select individual_id,
count(distinct visit_date) / count(distinct cal_month_nbr)
from ww_customer_dl_secure.cust_scan c
group by individual_id;
Actually, Hive may not be efficient at calculating count(distinct), so multiple levels of aggregation might be faster:
select individual_id, avg(num_visit_days)
from (select individual_id, cal_month_nbr, count(*) as num_visit_days
from (select distinct individual_id, visit_date, cal_month_nbr
from ww_customer_dl_secure.cust_scan c
) iv
group by individual_id, cal_month_nbr
) ic
group by individual_id;

How to write a sql script for a range of Oracle assignment date records by different employee's job titles

I am trying to write an ad-hoc query for a range of assignment date records by employee's job title. These examples are used for the Oracle application assignment table.
First sample:
AsgId Start_Date End_Date Job_ID
1 1/1/14 6/30/14 10
1 7/1/14 11/15/14 10
1 11/16/14 1/10/15 20
1 1/11/15 3/10/15 10
1 3/11/15 3/31/15 10
1 4/1/15 12/31/18 20
I have tried analytical functions, in-line views, and other code without success.
Expected report results of 3 date-range records by job title:
asgid start_date end_date job_title
1 1/1/14 11/15/14 10
1 11/16/14 1/10/15 20
1 1/11/15 3/31/15 10
1 4/1/15 12/31/18 20
Second sample:
EMP_ID START_DATE END_DATE JOB_TITLE
1 1/1/14 11/15/14 10
1 11/16/14 11/10/15 10
1 11/11/15 12/31/15 20
1 1/1/16 1/31/16 10
1 2/1/16 12/31/16 10
Expected report results of 3 date-range records by job title
EMP_ID START_DATE END_DATE JOB_TITLE
1 1/1/14 11/10/15 10
1 11/11/15 12/31/15 20
1 1/1/16 12/31/16 10
This is a type of gaps-and-islands problem. Assuming that there are no gaps or overlaps, you can use left join and a cumulative sum to determine the islands. The rest is aggregation:
select asgid, job_id, min(start_date) as start_date,
max(end_date) as end_date
from (select a.*,
sum(case when aprev.asgid is null then 1 else 0 end) over (partition by a.asgid, a.job_id order by a.start_date) as grp
from assignment a left join
assignment aprev
on aprev.asgid = a.asgid and
aprev.job_id = a.job_id and
aprev.end_date = a.start_date - 1
) a
group by asgid, job_id, grp
order by asgid, min(a.start_date);
Here is a db<>fiddle.

SQL: Select all from column A and add a value from column B if present

I'm having quite an easy problem with SQL, I just can't word it properly (therefore I didn't find anything in google and my title probably is misleading)
The problem is: I have a big table containing transaction informations in the form (ID, EmployeeID, Date, Value) (and some more, but only those matter currently) and a list of all EmployeeIDs. What I want is a result table showing all employee IDs with their aggregated value of transactions in a given timespan.
The problem is: How do I get those employees into the result table that don't have an entry for the given time period?
e.g.
ID EMPLID DATE VALUE
1 1 2013-01-01 1000
2 2 2013-02-02 2000
3 1 2013-01-03 3000
4 2 2013-04-01 2000
5 2 2013-03-01 2000
6 1 2013-02-01 4000
EMPLID NAME
1 bob
2 alice
And now I want the aggregated value of all transactions after 2013-03-01 like this
EMPLID VALUE
1 0 <- how to get this based on the employee table?
2 4000
The SQL Server in use is Firebird and I connect to it through JDBC (if that matters)
SELECT a.EmpID, a.Name,
COALESCE(SUM(b.Value), 0) TotalValue
FROM Employee a
LEFT JOIN Transactions b
ON a.EmpID = b.EmpID AND
b.Date >= '2013-03-01'
GROUP BY a.EmpID, a.Name
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins