How to get cumulative record In SQL Server? - sql-server

I have some data in SQL Server in below format.
declare #statement table
(
acctno int,
statDate date,
tod int,
lastDate date
)
insert into #statement select 123,'2018-02-12',567,'2018-01-12'
insert into #statement select 123,'2018-03-12',580,'2018-02-12'
insert into #statement select 123,'2018-04-12',567,'2018-03-12'
--select * from #statement
declare #txn table
(
acct int,
txndate date,
amount int
)
insert into #txn select 123,'2018-02-11',400
insert into #txn select 123,'2018-02-18',400
insert into #txn select 123,'2018-02-25',400
insert into #txn select 123,'2018-03-11',400
insert into #txn select 123,'2018-03-25',400
Result of the both tables similar like below.
]1
Now I want the result as shown here:
and I am trying to get it with this query:
;with cte as
(
select
acctno, statDate, tod, txndate, amount, lastDate
from
#statement
inner join
#txn on acctno = acct
)
select *
from #txn t
left join cte on acct = acctno
and t.txndate between statDate and lastDate
But the result is not being returned as expected - please help me get the desired result.

I think that you can do this more simply
select s.acctno,statDate,tod,txndate,amount,lastDate
from #txn t
Inner join #statement s
On s.acctno = t.acct
And t.txndate Between s.lastDate and s.startDate
You may need to change the BETWEEN to a “<“ for the startDate comparison.

This is a clasical DKNF join :
WITH TD AS(
SELECT T1.acctno, T1.statDate AS StartDate, T1.tod, COALESCE(MAX(T2.statDate), '1-01-01') AS BeforeDate
FROM #statement AS T1
LEFT OUTER JOIN #statement AS T2
ON T1.acctno = T2.acctno AND T1.statDate < T2.statDate
GROUP BY T1.acctno, T1.statDate, T1.tod
)
SELECT acctno, StartDate, tod, txndate, amount
FROM TD
JOIN #txn AS t
ON TD.acctno = t.acct AND txndate <= StartDate AND txndate > BeforeDate

Related

Can I "left join" days between 2 dates in sql server?

There is a table in SQL Server where data is entered day by day. In this table, data is not filled in some days.
Therefore, there are no records in the table.
Sample: dataTable
I need to generate a report like the one below from this table.
Create a table with all the days of the year. I know that I can output a report by "joining" the "dataTable" table.
But this solution seems a bit strange to me.
Is there another way?
the code i use for temp date table
CREATE TABLE tempDate (
calendarDate date,
PRIMARY KEY (calendarDate)
)
DECLARE
#start DATE= '2021-01-01',
#dateCount INT= 730,
#rowNumber INT=1
WHILE (#rowNumber < #dateCount)
BEGIN
INSERT INTO tempDate values (DATEADD(DAY, #rowNumber, #start))
set #rowNumber=#rowNumber+1
END
GO
select * from tempDate
This is how I join using this table
SELECT
*
FROM
tempDate td WITH (NOLOCK)
LEFT JOIN dataTable dt WITH (NOLOCK) ON dt.reportDate = td.calendarDate
WHERE
td.calendarDate BETWEEN '2021-09-05' AND '2021-09-15'
Create a table with all the days of the year. I know that I can output a report by "joining" the "dataTable" table.
This is the way. You can generate that "table" on the fly if you really want to, but normally the best way is to simply have a calendar table.
You can use common expression tables for dates. The code you need:
IF(OBJECT_ID('tempdb..#t') IS NOT NULL)
BEGIN
DROP TABLE #t
END
CREATE TABLE #t
(
id int,
dt date,
dsc varchar(100),
)
INSERT INTO #t
VALUES
(1, '2021.09.08', 'a'),
(1, '2021.09.09', 'b'),
(1, '2021.09.12', 'c')
DECLARE #minDate AS DATE
SET #minDate = (SELECT MIN(dt) FROM #t)
DECLARE #maxDate AS DATE
SET #maxDate = (SELECT MAX(dt) FROM #t)
;WITH cte
AS
(
SELECT #minDate AS [dt]
UNION ALL
SELECT DATEADD(DAY, 1, [dt])
FROM cte
WHERE DATEADD(DAY, 1, [dt])<=#maxDate
)
SELECT
ISNULL(CAST(t.id AS VARCHAR(10)), '') AS [id],
cte.dt AS [dt],
ISNULL(t.dsc, 'No record has been entered in the table.') AS [dsc]
FROM
cte
LEFT JOIN #t t on t.dt=cte.dt
The fastest method is to use a numbers table, you can get a date list between 2 dates with that:
DECLARE #Date1 DATE, #Date2 DATE
SET #Date1 = '20200528'
SET #Date2 = '20200625'
SELECT DATEADD(DAY,number+1,#Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number+1,#Date1) < #Date2
If you go go in LEFT JOIN this select, whit your table, you have the result that you want.
SELECT *
FROM (SELECT DATEADD(DAY,number+1,#Date1) [Date]
FROM master..spt_values WITH (NOLOCK)
WHERE type = 'P'
AND DATEADD(DAY,number+1,#Date1) < #Date2 ) as a
LEFT JOIN yourTable dt WITH (NOLOCK) ON a.date = dt.reportDate
WHERE td.[Date] BETWEEN '2021-09-05' AND '2021-09-15'

How to Insert into temp table Using SubQuery and Select from Temp table

I am trying to insert this data into a temp table
When I add the piece to insert into my temp table with the second result set #Temp
I recieve an incorrect syntax error
Any Ideas?
sql
-- =============================================
-- Author: <Kaven>
-- Create date: <August 2020>
-- Description: Summary Report of [spRPWipManufactureProcessLogR1]
-- Owner : RpData.dll
-- =============================================
ALTER PROCEDURE [dbo].[spRPWipManufactureProcessLogR2]
#FromDate DATE = null,
#ToDate DATE = null,
#Location NVARCHAR(15) =null, --Dropdown --CostCentre
#Operation NVARCHAR(15) = NULL, -- Dropdown --WorkCentre
#JobNumber nvarchar(15) = NULL
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN
--EXEC [spRPWipManufactureProcessLogR2] '20200201', '20200301'
IF #Operation = ''
BEGIN
SET #Operation = null
END
IF #JobNumber = ''
BEGIN
SET #JobNumber = NULL
END
IF OBJECT_ID(N'tempdb..#Temppp_WarehouseList') IS NOT NULL
BEGIN DROP TABLE #Temppp_WarehouseList END
SELECT StockCode
INTO #Temppp_WarehouseList
FROM CompanyA..InvMaster
DECLARE
#wh_List NVARCHAR(1000),
#wh_List2 NVARCHAR(1000)
SELECT #wh_List = STUFF((SELECT ',['+l.Warehouse+' QtyOnHand]' FROM CompanyA..InvWhControl l WHERE l.Warehouse IS NOT NULL FOR XML PATH('')),1,1,'')
SELECT #wh_List2 = STUFF((SELECT ',['+l.Warehouse+' QtyOnOrder]' FROM CompanyA..InvWhControl l WHERE l.Warehouse IS NOT NULL FOR XML PATH('')),1,1,'')
--SELECT #wh_List
--SELECT #wh_List2
SELECT ProductID,
FromDate,
ToDate,
QtyBUoM
INTO #TempBuOM
FROM Cetus.dbo.SMDemandForcastDailyHierarchy df
JOIN dbo.SMDemandSourceTypeDef st ON st.pkDFSourceTypeID = df.fkSourceType
WHERE
df.DemandSource = st.pkDFSourceTypeID
AND
df.Parent = st.pkDFSourceTypeID
AND FromDate <= GETDATE()
AND ToDate >= GETDATE()
SELECT * FROM #TempBuOM
SELECT * FROM #Temppp_WarehouseList t
INNER join
(SELECT * FROM
(SELECT Warehouse+' QtyOnHand' 'WarehouseOnHand', Warehouse+' QtyOnOrder' 'WarehouseOnOrder', QtyOnHand,QtyOnOrder,
b.CostCentre AS 'Location',
--b.WorkCentre AS [Operation],
-- arc.Job AS [Job Number],
--FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'HH:mm:ss') AS [Operation Compeleted Time],
-- CONVERT(VARCHAR, FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'yyyy/MM/dd'),100) AS [Operation Compeleted Date],
-- CONVERT(Date, CONVERT(date, arc.DTComplete))AS [Compeleted Date],
df.ProductID AS 'Product ID',
m.Description AS 'Stock Code DESCRIPTION',
arc.QtyToMake AS 'Quantity To Make',
arc.QtyManufactured 'Quantity Manufactured',
df.QtyBUoM AS 'Daily Demand',
inv.QtyOnOrder AS 'Quantity On Order',
inv.QtyOnHand AS 'Stock Levels'
INTO #TEMP -- Error comes here
FROM Cetus..WIPManufactureProcessLog s
LEFT JOIN WIP..WipMaster_Arc arc ON s.JobId = arc.Job
JOIN CompanyA..InvMaster m ON arc.StockCode = m.StockCode
JOIN CompanyA..InvWarehouse inv ON m.StockCode = inv.StockCode
JOIN CompanyA.dbo.BomOperations bo ON m.StockCode = bo.StockCode AND bo.Operation = s.Operation
JOIN CompanyA..BomWorkCentre b ON bo.WorkCentre = b.WorkCentre
JOIN [dbo].SMDemandForcastDailyHierarchy df ON m.StockCode = df.ProductID
JOIN dbo.SMDemandSourceTypeDef st ON st.pkDFSourceTypeID = df.fkSourceType
--EXEC [spRPWipManufactureProcessLogR2] '20190101', '20200201'
Where CONVERT(VARCHAR, FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'yyyy/MM/dd'),100)
BETWEEN ISNULL(#FromDate,CONVERT(VARCHAR, FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'yyyy/MM/dd'),100))
AND ISNULL(#ToDate,CONVERT(VARCHAR, FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'yyyy/MM/dd'),100))
--WHERE FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'HH:mm:ss') >= '2020-02-01'
--AND FORMAT(CAST(CAST(s.Event AS XML).value('(/OperationTrackingLog/TimeStamp)[1]', 'varchar(max)') AS DATETIME),'HH:mm:ss') <= '2020-03-01 '
AND m.WarehouseToUse <>'AA'
AND b.WorkCentre = ISNULL(#Location,b.WorkCentre )
AND b.CostCentre = ISNULL(#Operation,b.CostCentre )
AND arc.Job = ISNULL(#JobNumber,arc.Job) )p
PIVOT (
SUM(QtyOnHand) FOR WarehouseOnHand IN
([BB QtyOnHand],
[16 QtyOnHand],
[IS QtyOnHand],
[MS QtyOnHand],
[MH QtyOnHand],
[AA QtyOnHand],
[BC QtyOnHand],
[PH QtyOnHand],
[P4 QtyOnHand],
[PL QtyOnHand],
[CC QtyOnHand],
[SR QtyOnHand],
[TS QtyOnHand],
[WW QtyOnHand])) AS pvt
PIVOT
(SUM(QtyOnOrder) FOR WarehouseOnOrder IN
([BB QtyOnOrder],
[16 QtyOnOrder],
[IS QtyOnOrder],
[MS QtyOnOrder],
[MH QtyOnOrder],
[AA QtyOnOrder],
[BC QtyOnOrder],
[PH QtyOnOrder],
[P4 QtyOnOrder],
[PL QtyOnOrder],
[CC QtyOnOrder],
[SR QtyOnOrder],
[TS QtyOnOrder],
[WW QtyOnOrder])) AS pvt2 GROUP BY )
AS z on t.StockCode = z.[Product ID]
```sql```
Edit: Added answers in case the #TEMP table is supposed to have the inner query rather than the final pivot results.
Note that the 'code' provided is there to show structure - you'll need to add the slabs of text from above and bug-fix those as normal. The below is to demonstrate how to fix the issue.
That INTO #TEMP is in the middle of a FROM statement (it's not actually the final select) and therefore doesn't work.
If want the final results (e.g., from the pivot) to be stored in the temp table, remove the current 'INTO #TEMP' and put it into the outer query e.g.,
SELECT *
INTO #TEMP
FROM (your whole pivot statement) AS a
or alternatively using a CTE
; WITH CTE AS
(your whole pivot statement)
SELECT *
INTO #Temp
FROM CTE
If, on the other hand, you want to store the results of the inner query (not the pivot) in a temp table, then
run that first (e.g., take out the inner query you have there, into its own statement)
use the #temp table in the bigger query
-- Initial creation of temp table (SQL extracted from your current code)
SELECT Warehouse+' QtyOnHand' (... and rest of fields)
INTO #Temp
FROM Cetus..WIPManufactureProcessLog s
(... and rest of from, and where clauses)
-- And then use that in your pivot
SELECT *
FROM
(SELECT *
FROM #Temppp_WarehouseList t
INNER join #TEMP ON (... matching fields)
) p
PIVOT
(pivot commands etc)

What is the optimal way to get only latest ID's from table in SQL

I'm trying to get only a single row per Appointment Number in a table storing a history of appointments. It works fine with a few rows but then gets slower? Is this the best way to do this kind of check and I'm just missing some indexes or is there a better way?
DECLARE #temptable TABLE
(
id INT PRIMARY KEY NOT NULL
, ApptNumber INT NOT NULL
, ApptDate DATE NOT NULL
, Notes VARCHAR(50) NULL
)
INSERT INTO #temptable VALUES (1,1,'01-DEC-2018','First Appointment')
INSERT INTO #temptable VALUES (2,1,'01-DEC-2018','')
INSERT INTO #temptable VALUES (3,1,'01-DEC-2018','Rescheduled')
INSERT INTO #temptable VALUES (4,2,'02-DEC-2018','Second Appointment')
INSERT INTO #temptable VALUES (5,2,'02-DEC-2018','Cancelled')
INSERT INTO #temptable VALUES (6,3,'03-DEC-2018','Third Appointment')
INSERT INTO #temptable VALUES (7,4,'04-DEC-2018','Fourth Appointment')
SELECT * FROM #temptable
SELECT MAX(id) FROM #temptable GROUP BY ApptNumber
SELECT tt.* FROM #temptable tt
INNER JOIN (SELECT MAX(id) [Id] FROM #temptable GROUP BY ApptNumber) appts ON appts.Id = tt.id
Solution 1:
select * from (
SELECT f1.*, row_number() over(partition by ApptNumber order by id desc ) rang FROM #temptable f1
) tmp where rang=1
Solution 2:
with tmp as (
select ApptNumber, max(ID) MaxID
from #temptable
group by ApptNumber
)
select f1.* from #temptable f1 inner join tmp f2 on f1.ID=f2.MaxID
Solution 3:
select distinct f3.* from #temptable f1
cross apply
(
select top 1 * from #temptable f2
where f1.ApptNumber=f2.ApptNumber
order by f2.ID desc
) f3
Window function
SELECT tt.*
FROM (
SELECT *, row_number() over (partition by ApptNumber order by id desc) as rn
) tt
where tt.rn = 1

Pivot query in SQL Server

I want to build dynamic sql query based on following
SELECT P.Trackingno,PA.SKUId,SC.SKUName,count(PA.SKUId) as TotalSKUId
,sum(case when PA.IsAvailable = 1 then 1 else 0 end) AS IsAvailable
FROM ADMIN.posavailability PA
LEFT OUTER JOIN Admin.SKUCreation SC ON SC.TCID=PA.Skuid
LEFT OUTER JOIN Admin.POSVisitDetails PD on PD.VisitId=PA.VisitID
LEFT OUTER JOIN Admin.POS P ON P.TrackingNo=PD.TrackingNo
WHERE PA.VisitId in
(SELECT visitid FROM Admin.POSVisitDetails PD WHERE PD.month=2 and PD.year=2017)
and PA.IsActive=1
GROUP BY P.Trackingno,PA.SKUId,SC.SKUName,PD.Month,PD.year
ORDER BY P.Trackingno
I got out as follows:
My desired output is:
Can any one help for dynamic pivot SQL query.
Here maybe help you.
Dynamic sql query
CREATE TABLE TrackingTbl
(
TrackingNo int,
SKUID int,
SKUName varchar(50),
TotalSKUID int,
IsAvaiable int
)
INSERT INTO TrackingTbl VALUES (1234,1,'Red',2,2)
INSERT INTO TrackingTbl VALUES (1234,2,'White',2,1)
INSERT INTO TrackingTbl VALUES (1234,3,'Blue',2,0)
INSERT INTO TrackingTbl VALUES (1234,4,'Yellow',2,2)
INSERT INTO TrackingTbl VALUES (3456,1,'Red',3,3)
INSERT INTO TrackingTbl VALUES (3456,2,'White',3,2)
INSERT INTO TrackingTbl VALUES (3456,3,'Blue',3,1)
INSERT INTO TrackingTbl VALUES (3456,4,'Yellow',3,0)
DECLARE #Columns varchar(200)
SET #Columns = Stuff((SELECT concat(', [',td.SKUName,']') FROM (select DISTINCT tt.SKUName FROM TrackingTbl tt ) td FOR XML PATH (''))
,1,1,'')
DECLARE #Query nvarchar(max) = CONCAT(
'SELECT TrackingNo,TotalSKUID,',#Columns,
' FROM
(
SELECT tt.IsAvaiable, tt.SKUName ,tt.TrackingNo, tt.TotalSKUID
FROM TrackingTbl tt
) sc
PIVOT
(
sum(IsAvaiable) FOR SKuName IN (',#Columns,' )
) pvt')
exec sp_executesql #Query
DROP TABLE dbo.TrackingTbl
Try this using MAX ()
;with cte as (
SELECT P.Trackingno,PA.SKUId,SC.SKUName,count(PA.SKUId) as TotalSKUId
,sum(case when PA.IsAvailable = 1 then 1 else 0 end) AS IsAvailable
FROM ADMIN.posavailability PA
LEFT OUTER JOIN Admin.SKUCreation SC ON SC.TCID=PA.Skuid
LEFT OUTER JOIN Admin.POSVisitDetails PD on PD.VisitId=PA.VisitID
LEFT OUTER JOIN Admin.POS P ON P.TrackingNo=PD.TrackingNo
WHERE PA.VisitId in
(SELECT visitid FROM Admin.POSVisitDetails PD WHERE PD.month=2 and PD.year=2017)
and PA.IsActive=1
GROUP BY P.Trackingno,PA.SKUId,SC.SKUName,PD.Month,PD.year
ORDER BY P.Trackingno
)
select trackingno,totalskuid,max(case when skuname='Red' then isavailable else '' end) Red,
max(case when skuname='White' then isavailable else '' end) White,
max(case when skuname='Blue' then isavailable else '' end) Blue,
max(case when skuname='Yellow' then isavailable else '' end) Yellow
from cte
group by trackingno,totalskuid

How to solve this variable pass into batch_date?

I want to pass in #batch date into batch_date...But it shows error...The error is
Column 'dbo.tnx_tid_InvCheck_Details.Batch_Date' is invalid in the
select list because it is not contained in either an aggregate
function or the GROUP BY clause.
The InvCheck_Details table has batch_date for each and every part_no. I want to group the part_no so that I can count(tid) and sum(tid_bal) by part_no. What should i do in order to run this script? TQ...
DECLARE #batch_date datetime
SET #batch_date = '2012-10-13 00:00:00.000'
CREATE TABLE #inv_check
(batch_date datetime,part_no varchar(25),Number_of_tid int,Updated_DT int, Tot_Tid_Bal int)
INSERT INTO #inv_check
SELECT batch_date,part_no,COUNT(tid)as Number_of_tid,0,sum(Tid_Bal)
FROM dbo.tnx_tid_InvCheck_Details
where batch_date = #batch_date
Group by part_no
order by part_no
UPDATE #inv_check
SET Updated_DT = isnull(d.Updated_DT,0)
--select i.part_no,i.Number_of_tid, isnull(d.Updated_DT,0)
FROM #inv_check i
LEFT OUTER JOIN
(SELECT part_no, COUNT(LastUpdate_DT)as Updated_DT,
sum(tid_bal) as Tid_bal_sum
FROM dbo.tnx_tid_InvCheck_Details
Where NOT LastUpdate_DT IS NULL
Group by part_no) d on i.part_no=d.part_no
DECLARE #sql int
DECLARE #sql1 int
SELECT #sql1 = count(part_no)
FROM #inv_check
SELECT #sql = count(part_no)
FROM #inv_check
WHERE number_of_tid= Updated_DT
SELECT #sql AS Parts_Counted,#sql1 AS Full_Parts
Drop table #inv_check
Try this
INSERT INTO #inv_check
Select y.batch_date,x.*
From dbo.tnx_tid_InvCheck_Details y
Join(
SELECT part_no,COUNT(tid)as Number_of_tid,0 AS Updated_DT,sum(Tid_Bal) As Tot_Tid_Bal
FROM dbo.tnx_tid_InvCheck_Details
where batch_date = #batch_date
Group by part_no
)x
On x.part_no = y.part_no
order by x.part_no

Resources