Count records where the date is last month - sql

I have a table like this
And then I want to add a column besides Total column. The column is LastMonthTotal with the same record but the date is last month before. How can I do that?
Here's the DDL
CREATE TABLE [dbo].[ERA_Report2]
(
[RESULT] [nvarchar](255) NULL,
[CLASSIFICATION_2] [nvarchar](255) NULL,
[ARMADA] [nvarchar](255) NULL,
[CDAREA] [nvarchar](255) NULL,
[BRAND] [nvarchar](255) NULL,
[MODEL] [nvarchar](255) NULL,
[Shift] [nvarchar](255) NULL,
[AST_POINT] [nvarchar](255) NULL,
[SOURCE] [nvarchar](255) NULL,
[AREA] [nvarchar](255) NULL,
[POST DATE] [nvarchar](255) NULL,
[PRICE] [float] NULL,
[DISC] [float] NULL,
[Net Payment] [float] NULL
)
My query is like this:
WITH step1 AS (
SELECT [RESULT],[CLASSIFICATION_2],[ARMADA],[CDAREA],[BRAND],[MODEL],[Shift],[AST_POINT],[SOURCE],[AREA]
,CONVERT(DATE, [POST DATE]) AS [POST DATE],COUNT(*) AS Total
FROM [AstraWorldDB].[dbo].[ERA_Report2]
GROUP BY [RESULT],[CLASSIFICATION_2],[ARMADA],[CDAREA],[BRAND],[MODEL],[Shift],[AST_POINT],[SOURCE],[AREA]
,[POST DATE]
),
step2 AS (
SELECT [RESULT],[CLASSIFICATION_2],[ARMADA],[CDAREA],[BRAND],[MODEL],[Shift],[AST_POINT],[SOURCE],[AREA]
,[POST DATE],Total
,CASE
WHEN MONTH([POST DATE]) > DATEPART(MONTH, DATEADD(MONTH, -1, [POST DATE]))
THEN (SELECT COUNT(*)
FROM step1
WHERE DATEPART(MONTH, [POST DATE]) = DATEPART(MONTH, DATEADD(MONTH, -1, [POST DATE])) AND
DATEPART(YEAR, [POST DATE]) = DATEPART(YEAR, DATEADD(MONTH, -1, [POST DATE]))
)
ELSE '0'
END AS LastMonthTotal
FROM step1
)
SELECT *
FROM step2
WHERE AREA = 'DPS'
ORDER BY [POST DATE]
but it keeps returning 0 when it shouldn't. This is the result:
result
where POST DATE = 2020-02-01, LastMonthTotal must be 2.

In all supported versions of SQL Server, you would use LAG() -- assuming that every month has data:
select t.*,
lag(total) over (partition by [RESULT],[CLASSIFICATION_2], [ARMADA],[CDAREA], [BRAND], [MODEL], [Shift], [AST_POINT], [SOURCE], [AREA] order by [POST DATE]) as prev_month_total
from <your table> t;
This seems like a reasonable assumption.
In older versions, you would presumably use a join:
select t.*, tprev.total
from <your table> t left join
<your table> tprev
on tprev.result = t.result and . . . -- all the columns that define the group
tprev.post_date = dateadd(month, -1, t.post_date)

Related

Add two datetime columns and divide result by 2 in SQL Server

If actual start date != ‘’ and complete date != '' calculate the mid trim date = (actual start date + complete date)/2
My table
CREATE TABLE [dbo].[AR_Placebook]
(
[Region] nvarchar(255) NULL,
[Network Area Description] [nvarchar](255) NULL,
[Substation] [nvarchar](255) NULL,
[Circuit] [nvarchar](255) NULL,
[Original (O) or Added Circuit (A)] [nvarchar](255) NULL,
[OC] [nvarchar](255) NULL,
[Line Miles] [float] NULL,
[Line Miles Complete] [float] NULL,
[Percent Complete] [float] NULL,
[Contractor] [float] NULL,
[Final Circuit Performance Audit] [nvarchar](255) NULL,
[Should Be Billed] [float] NULL,
[Invoiced to Date] [float] NULL,
[Gap in Billing Difference] [float] NULL,
[VCKT Number] [nvarchar](255) NULL,
[Bid Cost ] [float] NULL,
[Bid Cost per Line Mile] [float] NULL,
[Predictive Dialer Start Date] [nvarchar](255) NULL,
[ESTIMATED TRIM QUARTER] [nvarchar](255) NULL,
[Actual Start Date] [datetime] NULL,
[Complete Date] [datetime] NULL,
[MidTrimDate] [datetime] NULL
)
I have tried this
DECLARE #StartTime DATETIME
,#EndTime DATETIME
DECLARE #TotalWorkingHours varchar(50)
Declare #HalfDayCalculate varchar(50)
Declare #DivdeWorkingHours int
set #DivdeWorkingHours=2
SELECT #TotalWorkingHours = CONVERT(VARCHAR(8), DATEADD(SECOND,DATEDIFF(SECOND,#StartTime, #EndTime),0), 108)
from AR_Placebook
where #StartTime=[Actual Start Date] and
#EndTime =[Complete Date] and
[Actual Start Date]!='' and
[Complete Date]!=''
set #HalfDayCalculate = convert(TIME(0), dateadd(second, datediff(second, 0, #TotalWorkingHours) / #DivdeWorkingHours, 0),108)
select #HalfDayCalculate as MidTrimDate
You can go with different approach - calculate the date difference between the two dates using DATEDIFF (https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver15), divide the result of the DATEDIFF by 2 and subtract this value from the complete date.
Please find below the answer as per your requirement.
SELECT [start date],DATEADD(DAY,day_difference,[start date]) AS [mid_date],[complete date],day_difference
FROM
(
SELECT '2020-03-01' AS[start date], '2020-03-20' AS[complete date],DATEDIFF(DAY,'2020-03-01' ,'2020-03-20')/2 as day_difference
)A
Also, find below snap.
enter image description here
If actual start date != ‘’ and complete date != '' calculate the mid trim date = (actual start date + complete date)/2
I think you are looking for. For the middle day:
select dateadd(day,
datediff(day, start_date, complete_date) / 2,
start_date
)
If there is a time component, use a smaller time unit:
select dateadd(second,
datediff(second, start_date, complete_date) / 2,
start_date
)

SQL select command consume 100% CPU while executing

In my query I'm Selecting row by row closing balance. It's consume 100% CPU while executing is sql server 2014.
Here is my query:
;WITH summary(id,reference_id,entry_date,particular,remarks,debit,credit,balance)AS(
SELECT
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
(credit-debit)+(SELECT ISNULL(SUM(l.credit-l.debit) ,0) FROM member_transaction l WHERE l.entry_date<a.entry_date AND l.member_id=#mId AND is_succeed=1 AND isnull(l.reference_id,0) NOT IN(SELECT user_reference_id FROM recharge_request WHERE status='Failure'))AS balance
FROM member_transaction a
WHERE member_id=#mId AND is_succeed=1
AND isnull(reference_id,0) NOT IN(SELECT user_reference_id FROM recharge_request WHERE status='Failure')),
openingbalance(
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
balance
)AS(SELECT TOP 1 0,'','','OPENING BALANCE','',0,0,balance FROM summary WHERE entry_date<'2017/03/10' ORDER BY entry_date DESC
)SELECT * FROM openingbalance UNION SELECT * FROM summary ORDER BY entry_date DESC
Is there any other way to calculate row by row closing balance on every transaction? Please help me to solve this problem.
HERE is table structure:
CREATE TABLE [member_transaction](
[id] [int] IDENTITY(1,1) NOT NULL,
[member_id] [int] NULL,
[t_type] [varchar](50) NULL,
[debit] [decimal](12, 2) NOT NULL,
[credit] [decimal](12, 2) NOT NULL,
[particular] [varchar](100) NULL,
[remarks] [varchar](150) NULL,
[reference_id] [varchar](50) NULL,
[entry_date] [datetime] NOT NULL,
[is_succeed] [bit] NOT NULL
)
CREATE TABLE [recharge_request](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[mobile_no] [varchar](50) NULL,
[amount] [decimal](12, 0) NULL,
[user_reference_id] [varchar](50) NULL,
[uid] [int] NULL,
[rdate] [datetime] NOT NULL,
[status] [varchar](50) NOT NULL
)
Assuming you're in SQL Server 2012+, you should try something like this:
SELECT
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
sum(isnull(credit,0)-isnull(debit,0)) over (order by entry_date asc) AS balance
FROM
member_transaction a
WHERE
member_id=#mId AND
is_succeed=1 AND
not exist (select 1 FROM recharge_request r WHERE r.user_reference_id = a.reference_id and r.status='Failure')
If you want to fetch more than one member, then you should have partition by in the over part of the sum.

Joining CTE_1 to CTE_2 if CTE_2 has data, if not just give CTE_1 Data

Is there a way to join CTE_1 to CTE_2 if CTE_2 has data? With this code, it returns nothing if CTE_2 has no data. The common columns are Names and Locations. The issue that I am having is CTE_1 will always have data, but CTE_2 won't get data until around 4-6 hours into the shift.
Begin
Create table #Punches
(
[AEmployeeID] [varchar](255) NULL,
[APERSONFULLNAME] [varchar](255) NULL,
[ACUSTOMER] [varchar](255) NULL,
[ADEPARTMENT] [varchar](255) NULL,
[AEVENTDATE] [varchar](255) NULL,
[AINPUNCHDTM1] [varchar](255) NULL,
[AOUTPUNCHDTM1] [varchar](255) NULL,
[AINPUNCHDTM2] [varchar](255) NULL,
[AOUTPUNCHDTM2] [varchar](255) NULL,
[AINPUNCHDTM3] [varchar](255) NULL,
[AOUTPUNCHDTM3] [varchar](255) NULL,
[ASUPERVISORNAME] [varchar](255) NULL,
[ASUPERVISORID] [varchar](255) NULL,
[ASHIFTSTARTTIME] [varchar](255) NULL,
[ASHIFTENDTIME] [varchar](255) NULL,
[ASITE] [varchar](255) NULL,
[ABadge#] [varchar] (255) NULL
)
insert into #Punches
EXECUTE ('BEGIN FX_RPTSP_MEMPHIS_PUNCHES(); END;') at KR1P1;
end
Begin
Create table #1stScans
(
ID int identity ,
[AEmployee Name] [varchar](255) NULL,
[Location] [varchar](25) NULL,
[Dispatch] [varchar](30) NULL,
[TimeStamp] [varchar](255) NULL
)
insert into #1stScans
Select * from Openquery(FFLOW,'Execute rudpBenchLocations_today');
end
--Selects Tech Name, Bench Location, 1st Punch, First Scan, and Dwell (COMPLETED and ACCURATE)
BEGIN
WITH CTE_1 AS(
Select
[AEmployee Name] Name1,
Location Location1,
#Punches.AINPUNCHDTM1 as FirstPunch,
Timestamp From
(Select [AEmployee Name],Location,TimeStamp,
ROW_NUMBER()OVER (PARTITION By [AEmployee Name] ORDER BY Timestamp ASC)Dup from #1stScans,#Punches)as FSD
Join #Punches ON [AEmployee Name]=APERSONFULLNAME
where FSD.dup = 1
AND Convert(Date,AINPUNCHDTM1) = Convert(Date,Getdate()))
,CTE_2 AS
(
Select [AEmployee Name] Name2,Location Location2,TimeStamp Timestamp2,AINPUNCHDTM2 LunchPunch,(ROW_NUMBER()OVER(PARTITION By [AEmployee Name] ORDER BY TimeStamp))as DUP from #1stScans
INNER JOIN #Punches ON [AEmployee Name]=APERSONFULLNAME
AND CONVERT(TIME,Timestamp)>=CONVERT(TIME,AINPUNCHDTM2)
)
***Select
Name1 as Name,
Location1 as Location,
TimeStamp as [1st TimeStamp],
FirstPunch,
TimeStamp2 as [2nd TimeStamp],
LunchPunch
FROM CTE_1
Join CTE_2 on Name1 = NAME2
WHERE DUP=1
AND Name2 <> ''***
END
Drop table #Punches
Drop table #1stScans
With a left join, conditions on the right hand table go in the JOIN conditions, not the where clause
Select
Name1 as Name,
Location1 as Location,
TimeStamp as [1st TimeStamp],
FirstPunch,
TimeStamp2 as [2nd TimeStamp],
LunchPunch
FROM CTE_1
LEFT Join CTE_2
on Name1 = NAME2
AND DUP=1
AND Name2 <> ''

Can I make this stored procedure faster

I have the stored procedure below. This stored procedure runs in 3-4 seconds even on my developer computer but on the server it takes 15-20 seconds. I tried to change some of subqueries to cross apply and some to outer apply. But it caused to take more longer time.
#startDate datetime ,
#endDate datetime ,
#customerId int
;WITH t1(Plate,UsedFuelTypeUID,RemainingBefore,DateRangeTotal,DateRangeTransactionsTotal,RemaininCurrent) AS
(
select
v.Plate, v.UsedFuelTypeUID,
isnull((select isnull( sum(vls1.FT_TotalLimit),0)
from VehicleChildLog vls1
where vls1.VehicleChildId =v.VehicleID and vls1.UpdateDate < #startDate
),0)-
isnull((select isnull( sum(t1.Liter),0) from Transactions t1
where t1.VehicleChildID=v.VehicleID and t1.SaleDate <#startDate
),0)as RemainingBefore,
sum(vl.FT_TotalLimit) DateRangeTotal,
isnull((select isnull( sum(t1.Liter),0) from Transactions t1
where t1.VehicleChildID=v.VehicleID and t1.SaleDate between #startDate and #endDate
),0) as DateRangeTransactionsTotal,
(v.FT_TotalLimit - v.FT_UsedTotalLimit) as RemainingCurrent
from VehicleChildLog vl
inner join VehiclesChild v on vl.VehicleChildId = v.VehicleID
where vl.CustomerChildID = #customerId and vl.UpdateDate between #startDate and #endDate
group by
v.VehicleID, v.Plate, v.UsedFuelTypeUID
,v.FT_TotalLimit - v.FT_UsedTotalLimit
)
select *, t1.RemainingBefore+t1.DateRangeTotal-t1.DateRangeTransactionsTotal as RemainingAfter from t1 ;
Table structure is below
[Transactions]
(
[TransactionID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[SaleDate] [datetime] NULL,
[Liter] [float] NULL,
[VehicleChildID] [int] NULL
...
)
[VehiclesChild]
(
[VehicleID] [int] IDENTITY(1,1) NOT NULL,
[CustomerChildID] [int] NULL,
[Plate] [varchar](16) NULL,
[UsedFuelTypeUID] [int] NULL,
[FT_TotalLimit] [float] NULL,
[FT_UsedTotalLimit] [float] NULL
...
)
[VehicleChildLog]
(
[VehiclesChildLogId] [int] IDENTITY(1,1) NOT NULL,
[VehicleChildId] [int] NOT NULL,
[CustomerChildId] [int] NOT NULL,
[FT_TotalLimit] [float] NULL,
[FT_UsedTotalLimit] [float] NULL,
[UpdateDate] [datetime] NULL
...
)

How can I PIVOT this data?

First, sorry for the middling title. Didn't have a ton of success on that front.
So - I have a table of data that has one row for each volunteer shift a person is scheduled for. Many people, being generous with their time, have signed up for multiple shifts. What I would like is to PIVOT this data s.t. I end up with one row per person, with sets of columns for each shift. I've spent about 90 minutes on this so far, but can't figure out how to PIVOT without an aggregation function applied.
What I mean by this is that each person is scheduled for at least one shift, so each person's row would have their unique ID, their name, their phone number, and their region. Then there would be a set of columns for Shift1 - role/status/start time/end time/etc. - which everyone would have filled out since everyone has signed up for at least one shift. Then, the Shift2 set of columns would be populated for people who have signed up for 2+ shifts, Shift3 for people who signed up for 3+ shifts, etc.
My current table schema:
CREATE TABLE [dbo].[confirmexport](
[PersonID] [int] NULL,
[EventType] [varchar](14) NULL,
[Shift] [varchar](10) NULL,
[StartDate] [datetime] NULL,
[StartTime] [datetime] NULL,
[EndDate] [datetime] NULL,
[EndTime] [datetime] NULL,
[Location] [varchar](39) NULL,
[Role] [varchar](16) NULL,
[Status] [varchar](9) NULL,
[FirstName] [varchar](20) NULL,
[LastName] [varchar](22) NULL,
[Phone] [bigint] NULL,
[Region] [varchar](9) NULL
) ON [PRIMARY]
All columns but PersonID, FirstName, LastName, Phone, and Region are shift-specific.
In an ideal world, I'd end up with a table that looked something like so:
CREATE TABLE [dbo].[confirmexportpivoted](
[PersonID] [int] NULL,
[Phone] [bigint] NULL,
[FirstName] [varchar](20) NULL,
[LastName] [varchar](22) NULL,
[Region] [varchar](9) NULL,
[EventType1] [varchar](14) NULL,
[Shift1] [varchar](10) NULL,
[StartDate1] [datetime] NULL,
[StartTime1] [datetime] NULL,
[EndDate1] [datetime] NULL,
[EndTime1] [datetime] NULL,
[Location1] [varchar](39) NULL,
[Role1] [varchar](16) NULL,
[Status1] [varchar](9) NULL,
[EventType2] [varchar](14) NULL,
[Shift2] [varchar](10) NULL,
[StartDate2] [datetime] NULL,
[StartTime2] [datetime] NULL,
[EndDate2] [datetime] NULL,
[EndTime2] [datetime] NULL,
[Location2] [varchar](39) NULL,
[Role2] [varchar](16) NULL,
[Status2] [varchar](9) NULL
) ON [PRIMARY]
Except with as many sets of columns as necessary for my data. OR - if that's a deal-breaker, I can definitely make do with 3. Any suggestions?
Thanks in advance - I am super-confused and would appreciate any and all help.
Well It was hard to me to reproduce the whole table, so I've worked only with Start and End Dates and Times, but solution should work for any number of columns. You can test it in SQL FIDDLE
SQL FIDDLE EXAMPLE
declare #columns nvarchar(max), #stmt nvarchar(max)
declare #Temp_Columns table (RowNum int, COLUMN_NAME nvarchar(128))
insert into #Temp_Columns
select R.RowNum, c.COLUMN_NAME
from
(
select row_number() over (partition by c.PersonID, c.FirstName, c.LastName, c.Phone, c.Region order by c.StartDate asc, c.EndDate asc) as RowNum
from confirmexport as c
) as R
inner join INFORMATION_SCHEMA.[COLUMNS] as c on c.TABLE_NAME = 'confirmexport' and c.COLUMN_NAME not in ('PersonID', 'FirstName', 'LastName')
order by 1, 2
select #columns = isnull(#columns + ', ', '') +
'min(case when A.RowNum = ' + cast(T.RowNum as nvarchar(128)) +
' then A.[' + T.COLUMN_NAME + '] else null end) as [' +
T.COLUMN_NAME + cast(T.RowNum as nvarchar(128)) + ']'
from #Temp_Columns as T
select #stmt = '
select
A.PersonId, A.FirstName, A.LastName, A.Phone, A.Region,' + #columns + '
from
(
select
c.*,
row_number() over (partition by c.PersonID, c.FirstName, c.LastName, c.Phone, c.Region order by c.StartDate asc, c.EndDate asc) as RowNum
from confirmexport as c
) as A
group by
A.PersonId, A.FirstName, A.LastName, A.Phone, A.Region'
exec sp_executesql
#stmt = #stmt