writing a query and giving a score - sql-server

I am trying to write a query for the following:
Count the number of transactions in the previous 90 days. Note: This needs to
be averaged out for new members = (No of transactions / Days being a
member) x 90
New members are the one whose DateCreated is between 0 and 90 days from todays date.
Table structure:
Column Name Datatype
---------------------------------
Member_No nvarchar(255)
Order_No int
Transaction_Date datetime
Net money
Date_Created datetime
Also, the final step is after counting the transactions, I need to give a score. So if a member has count more than 8 then give a score of 5.
Following are the ranges:`
Transaction count Score
>8 5
6-8 4
4-6 3
2-4 2
0-2 1
Let me know if any queries

Hope the below code works for you (Not tested because not having Schema.)
;WITH RANKS AS
(
SELECT 0 AS FROM_TR, 2 AS TO_TR, 1 AS SCORE
UNION ALL
SELECT 3 AS FROM_TR, 4 AS TO_TR, 2 AS SCORE
UNION ALL
SELECT 5 AS FROM_TR, 6 AS TO_TR, 3 AS SCORE
UNION ALL
SELECT 7 AS FROM_TR, 8 AS TO_TR, 4 AS SCORE
UNION ALL
SELECT 9 AS FROM_TR, NULL AS TO_TR, 5 AS SCORE
)
, MEMBER_TRANS AS (
SELECT Member_No AS MEMBER_NO
,Date_Created AS DATE_CREATED
,COUNT(DISTINCT Order_No) ACTUAL_TRANSACT_COUNT
,CASE
WHEN Date_Created BETWEEN DATEADD(DD, - 90, GETDATE())
AND GETDATE()
THEN CAST(
COUNT(DISTINCT Order_No) / DATEDIFF(DD, Date_Created, GETDATE()) * 90
AS INT)
ELSE COUNT(DISTINCT Order_No)
END AS TRANSACT_COUNT
FROM TABLE1
WHERE Transaction_Date BETWEEN DATEADD(DD, - 90, GETDATE())
AND GETDATE()
GROUP BY Member_No
,Date_Created
)
SELECT MT.Member_No,MT.TRANSACT_COUNT, R.SCORE FROM MEMBER_TRANS MT
INNER JOIN RANKS R ON MT.TRANSACT_COUNT BETWEEN R.FROM_TR
AND isnull(R.TO_TR,MT.TRANSACT_COUNT)
--Added Extra below code from your comments
UNION ALL
SELECT Member_No,COUNT(DISTINCT Order_No), 1 AS SCORE FROM TABLE1
WHERE Transaction_Date < DATEADD(DD, - 90, GETDATE())
AND Transaction_Date NOT BETWEEN DATEADD(DD, - 90, GETDATE())
AND GETDATE()
GROUP BY Member_No

The code will return the desired result as per your requirement.Please find the snapshot of output for below query.
WITH Mycte
AS
(
Select Member_No,Case when DateDiff(dd,Date_Created,Getdate())>90 then 0 else 1 END AS New_Member
, DateDiff(dd,Date_Created,Getdate()) AS DaysAsMember
,Count(Order_No) TransactionCount from #Sample1
group by Member_No,Date_Created
)
Select Member_No,Case when TransactionCount > 8 THEN 5
WHEN TransactionCount BETWEEN 6 AND 8 THEN 4
WHEN TransactionCount BETWEEN 4 AND 5 THEN 3
WHEN TransactionCount BETWEEN 3 AND 4 THEN 2
WHEN TransactionCount BETWEEN 0 AND 2 THEN 1
END
AS Score
From Mycte

Related

How get last n month of data for each ID from 2 tables using SQL

I have 2 tables, A and B. I want to have last 3 months of Db_date (table B) from the Start_Date (tableA) for each ID.
Table A
ID
Start_Date
1
2022-08-01
Table B
ID
Start_Date
Amount
1
2022-08-01
1000
1
2022-07-01
2000
1
2022-06-01
3000
1
2022-05-01
500
I know by using below code can get last 3 months from the current moth of Start_Date, but I want have last 3 months of Db_Date Amount from table B, for each Start_Date for each ID in Table A.
SELECT *
FROM TableA
WHERE Start_Date >= DATEADD(M, -3, GETDATE())
You could use an outer apply to get the sum of amount the last three months from TableB
SELECT *
FROM TableA a
OUTER APPLY(SELECT SUM(Amount) as SumAmountFor3MonthsAfterStart
FROM TableB
WHERE StartDate > DATEADD(M, -3, a.Start_Date)
) OA
WHERE Start_Date >= DATEADD(M, -3, GETDATE())

Date Comparison of Two Tables in SQL SERVER

I had this Data,
Table One :
EmpID Date Absent
1 01/01/2018 1
1 01/02/2018 1
1 02/05/2018 1
1 03/25/2018 1
1 04/01/2018 0
1 05/02/2018 1
1 06/03/2018 1
Table Two
ID Amount DateEffective
1 5.00 02/06/2018
2 3.00 05/02/2018
3 10.00 06/03/2018
Desired Output
EmpID Month Year Absent Penalty
1 January 2018 2 5.00
1 February 2018 1 5.00
1 March 2018 1 3.00
1 April 2018 0 3.00
1 May 2018 1 13.00
1 June 2018 1 10.00
This is my Code
SELECT { fn MONTHNAME(one.Date) } AS MonthName, YEAR(one.Date) AS Year, SUM(one.Absent) AS Absent,
(
SELECT top 1 two.DailyRate
FROM table_two as two
WHERE EmpID = '1'
AND one.Date <= two.EffectivityDate
)
FROM table_one as one
WHERE EmpID = '1'
GROUP BY { fn MONTHNAME(one.Date) }, MONTH(one.Date), YEAR(one.DTRDate)
ORDER BY Year(one.Date),month(one.Date)
and it shows an error :
Column 'one.Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
please help for this issue...
Thanks
Try this :
SELECT
one.EmpID
,DATENAME(MONTH,one.Date) AS [MonthName]
,YEAR(one.Date) AS [Year]
,SUM(one.Absent) AS [Absent]
,(SELECT top 1 two.Amount
FROM table_two as two
WHERE two.ID = one.EmpID
AND YEAR(two.DateEffective) >= YEAR(one.Date)
AND MONTH(two.DateEffective) >=MONTH(one.Date)
) AS [Penalty]
FROM table_one as one
WHERE
one.EmpID = '1'
GROUP BY one.EmpID,DATENAME(MONTH,one.Date), MONTH(one.Date), YEAR(one.Date)
ORDER BY Year(one.Date),month(one.Date)
From my understanding to do this,
select e.EmpID
,datename(month,e.Date)[month]
,year(e.Date) [year]
,sum(e.Absent) as [Abscount]
,a.Amount
from
empl e left join abs a
on datename(month,e.Date)=DATENAME(month,a.DateEffective)
group by e.EmpID,DATENAME(MONTH,e.Date), MONTH(e.Date), YEAR(e.Date) , a.Amount
order by Abscount desc
Revert me if any clarifications needed...
is this helpful.?
Create Table #TabOne(EmpID int,[Date] Date,[Absent] Bit)
Create Table #TabTwo(ID int,Amount float,DateEffective Date)
Insert into #TabOne
SELECT 1,'01/01/2018',1 Union All
SELECT 1,'01/02/2018',1 Union All
SELECT 1,'02/05/2018',1 Union All
SELECT 1,'03/25/2018',1 Union All
SELECT 1,'04/01/2018',0 Union All
SELECT 1,'05/02/2018',1 Union All
SELECT 1,'06/03/2018',1
Insert into #TabTwo
Select 1,5.00 ,'02/06/2018' Union All
Select 2,3.00 ,'05/02/2018' Union All
Select 3,10.00,'06/03/2018'
;with cte1
As
(
Select One.EmpID,MONTH(one.[Date]) As [mon],YEAR(one.[Date]) As [Year],two.Amount,one.[Absent],
ROW_NUMBER() OVER(partition by One.EmpID,One.[Date] order by DATEDIFF(dd,two.DateEffective,one.[Date]) desc) as rn
from #TabOne one
LEFT JOIN #TabTwo two on one.[Date]<=two.DateEffective
)
Select EmpID,DATENAME(month, DATEADD(month, [mon]-1, CAST('2008-01-01' AS datetime))) As [Month],
[Year],SUM(CASE WHEN [Absent]=0 then 0 ELSE 1 END) As [Absent] ,MAX(Amount) As Penalty
from cte1
where rn=1
Group by EmpID,[Year],[mon]
order by EmpID,[Year],[mon]
Drop Table #TabOne
Drop Table #TabTwo

How can I get count of rows for every week?

I have select from table like:
SELECT DATEPART(WEEK, DayTime) as WeekNumber FROM dbo.Transactions
Result:
WeekNumber
1
1
1
2
2
3
4
4
5
4
5
3
How can I get count of rows for every number of week?
I need something like this:
WeekNumber CountOfRows
1 3
2 2
3 2
4 3
5 1
You need to GROUP BY week number and use COUNT function
SELECT DATEPART(WEEK, DayTime), COUNT(*)
FROM dbo.Transactions
GROUP BY DATEPART(WEEK, DayTime)
SELECT DATEPART(WEEK, DayTime) as WeekNumber, COUNT(1) as CountOfRows
FROM dbo.Transactions
GROUP BY WeekNumber;

How do I count the occurrence of a value in a column of type 2 slowly changing dimension?

I have my question altered as is viewed as vague. I have a table as below:
Id AltId DateFrom DateTo CurrentFlag Value
1 23 2015-04-01 2015-05-31 0 0
2 23 2015-05-31 Null 1 50
3 45 2015-06-01 Null 1 0
4 60 2015-07-01 Null 1 0
I want to achieve a count where Value is 0 for the past six months. Expected results:
Month Count
4 1
5 1
6 1
7 2
8 2
9 2
This is supposed to be cumulative count but the AltId ceases in a month where it changes value to anything greater than 0 like is the case with AltId 23.
Cumulative count is not an issue but how to not include an AltId when it's value changes from 0.
I'm not sure if this makes sense this time around. I'm using Sql Server 2008.
I'm wondering why this script doesn't do what I expect:
declare #a table
(
id int
,altId int
,startDate date
,endDate date
,currentFlag bit
,value int
)
insert into #a
values
(1,23,'2015-04-01','2015-05-31',0,0)
,(2,23,'2015-05-31',null,1,50)
,(3,45,'2015-06-01',null,1,0)
,(4,60,'2015-07-01',null,1,0)
declare #s date =DATEADD(m, -5, convert(date, convert(varchar(6), getdate(),112) + '01')), #e date = getdate();
;with d([Month],DateKey) as
(
select month(#s) [Month],#s DateKey
union all
select
month(DateKey),dateadd(day,1,DateKey)
from
d
where d.DateKey>= #s and d.DateKey<=#e
)
select
d.Month
,count(distinct a.altId) as 'Count'
from
d
left join
#a a
on
d.dateKey between a.startDate and isnull(a.endDate,getdate())
and
a.value=0
group by
d.[Month]
option (maxrecursion 186)
Any idea?
This does the trick.
declare #a table
(
id int
,altId int
,startDate date
,endDate date
,currentFlag bit
,value int
)
insert into #a
values
(1,23,'2015-04-01','2015-05-31',0,0)
,(2,23,'2015-05-31',null,1,50)
,(3,45,'2015-06-01',null,1,0)
,(4,60,'2015-07-01',null,1,0)
declare #s date =DATEADD(m, -5, convert(date, convert(varchar(6), getdate(),112) + '01')), #e date = getdate();
select #s,#e
;with d([Month],DateKey) as
(
select month(#s) [Month],#s DateKey
union all
select
month(dateadd(day,1,DateKey)),dateadd(day,1,DateKey)
from
d
where d.DateKey>= #s and dateadd(day,1,DateKey)<=#e
)
select
d.Month
,count(distinct a.altId) as 'Count'
from
d
left join
#a a
on
d.dateKey between a.startDate and isnull(a.endDate,getdate())
and
a.value=0
group by
d.[Month]
option (maxrecursion 186)

How to get the records grouping dates for a span of 3 days in SQL?

It's getting difficult to group and display records every 5 days.
Here is my data:
FLIGHT_DATE LANDINGS PILOTID COPILOTNAME MONT DPT
11/16/2013 1 A B 11 5.5
11/17/2013 1 A B 11 13
11/19/2013 1 A B 11 12.55
11/19/2013 1 A B 11 4
11/21/2013 1 A B 12 6
11/24/2013 1 A B 12 6.03
11/25/2013 1 A B 11 5.5
11/26/2013 1 A B 11 13
11/26/2013 1 A B 11 12.55
11/30/2013 1 A B 11 4
12/1/2013 1 A B 12 6
12/2/2013 1 A B 12 6.03
I want to show it as below:
Week Start Week End DPT
11/17/2013 11/21/2013 35.55
11/22/2013 11/26/2013 37.08
11/27/2013 12/1/2013 6
12/2/2013 12/6/2013 6.03
Here it is my proposed solution:
DECLARE #MinDate AS DATETIME = (SELECT MIN(flight_date) FROM flights);
WITH cte
AS
(
SELECT
flight_date, DATEDIFF(DAY, #MinDate, flight_date) AS NoDays,
DATEDIFF(DAY, #MinDate, flight_date)/5 AS NoGroup,
DPT
FROM flights
)
SELECT
DATEADD(DAY, NoGroup*5, #MinDate) AS [Week Start],
DATEADD(DAY, NoGroup*5+4, #MinDate) AS [Weed End],
SUM(DPT)
FROM cte
GROUP BY NoGroup;
The idea is to form groups of 5 days, then associate a record to a specific group based on division with 5. NoDays represents the days spent from MinDate to Flight_Date.
You can use this query. You need to specify the start date from which you want to count and the number of days in each period (which seems to be 5 in your case) but please adjust those numbers as needed.
declare #startdate date = '20131117'
declare #interval int = 5
select dateadd(dd, #interval * (o.number - 1), #startdate) WeekStart,
dateadd(dd, #interval * o.number - 1, #startdate) WeekEnd,
sum(d.DPT) DPT
from yourtable d
inner join
(select ROW_NUMBER() over (order by object_id) as number from sys.all_objects) as o
on d.FLIGHT_DATE >= dateadd(dd, #interval * (o.number - 1), #startdate)
and d.FLIGHT_DATE < dateadd(dd, #interval * o.number, #startdate)
group by o.number
order by dateadd(dd, #interval * (o.number - 1), #startdate)

Resources