Default to a value when a sub-query statement fails? - sql

I have the following query:
INSERT INTO dbo.ResourceOrderCustomersOrders
( OrderId ,
Type ,
CustomerId ,
ResourceId ,
Quantity ,
Created ,
CreatedBy
)
VALUES ( ( SELECT MAX(OrderId) + 1
FROM dbo.ResourceOrderCustomersOrders
) , -- OrderId - int
'PENDING' , -- Type - varchar(50)
( SELECT MAX(CustomerId)
FROM dbo.ResourceOrderCustomers
WHERE UPPER(FirstName) = UPPER(#Firstname)
AND UPPER(Surname) = UPPER(#Surname)
AND UPPER(Email) = UPPER(#Email)
) , -- CustomerId - int
( SELECT MAX(ResourceId)
FROM dbo.ResourceOrderFormContent
WHERE DisplayTitle = #ResourceName
) , -- ResourceId - int
#ResourceQuantity ,
GETDATE() , -- Created - datetime
'WebsiteForm' -- CreatedBy - varchar(20)
);
In cases where a subquery fails I'd like to default to a value of my choosing (to hold unspecified records).
For example, were the following to fail to retrieve a result because a record doesn't exist:
SELECT MAX(ResourceId)
FROM dbo.ResourceOrderFormContent
WHERE DisplayTitle = #ResourceName
Then I would want to return the number '999' (unspecified record). What would be the best way to approach this?
I've tried to use try / catch but I'm being told this is invalid syntax. Here is my attempt:
INSERT INTO dbo.ResourceOrderCustomersOrders
( OrderId ,
Type ,
CustomerId ,
ResourceId ,
Quantity ,
Created ,
CreatedBy
)
VALUES ( ( SELECT MAX(OrderId) + 1
FROM dbo.ResourceOrderCustomersOrders
) , -- OrderId - int
'PENDING' , -- Type - varchar(50)
( SELECT MAX(CustomerId)
FROM dbo.ResourceOrderCustomers
WHERE UPPER(FirstName) = UPPER(#Firstname)
AND UPPER(Surname) = UPPER(#Surname)
AND UPPER(Email) = UPPER(#Email)
) , -- CustomerId - int
( BEGIN TRY
SELECT MAX(ResourceId)
FROM dbo.ResourceOrderFormContent
WHERE DisplayTitle = #ResourceName
END TRY
BEGIN CATCH
SELECT 999
END CATCH
) , -- ResourceId - int
#ResourceQuantity ,
GETDATE() , -- Created - datetime
'WebsiteForm' -- CreatedBy - varchar(20)
);

Max will always return NULL if no rows found. So You can use ISNULL.
SELECT ISNULL(MAX(ResourceId), 999)
FROM dbo.ResourceOrderFormContent
WHERE DisplayTitle = #ResourceName

Related

Update Temp Table

I need to update temp table in sql 2014 but this code seems wrong .
first i select all invoices and its Qty from invoices and set Inventory Qty with 0. and second statement i need to update each line by qty of inventory to compare later and use this code.declare #DifferenceTable table (
DataAreaId nvarchar(10) ,
SalesId nvarchar(50) ,
InvoiceId nvarchar(50) ,
ItemId nvarchar(50),
InvoiceQty decimal(16,4) ,
InventoryQty decimal(16,4)
)
insert into #DifferenceTable (DataAreaId , SalesId , InvoiceId , ItemId , InvoiceQty , InventoryQty )
select CustInvoiceTrans.DATAAREAID , CustInvoiceTrans.SALESID , CustInvoiceTrans.INVOICEID , CustInvoiceTrans.ITEMID , sum(CustInvoiceTrans.QTY) , 0. as InventoryQty
from CustInvoiceTrans with(nolock)
group by CustInvoiceTrans.DATAAREAID , CustInvoiceTrans.SALESID , CustInvoiceTrans.INVOICEID , CustInvoiceTrans.ITEMID
update #DifferenceTable
set InventoryQty = tt.Qty from
(select sum(InventTrans.QTY)*-1 as Qty , InventTransOrigin.DATAAREAID , REFERENCEID , InventTrans.INVOICEID , InventTrans.ITEMID
from InventTransOrigin
left join InventTrans on InventTrans.INVENTTRANSORIGIN = InventTransOrigin.RECID
and InventTrans.DATAAREAID = InventTransOrigin.DATAAREAID
and InventTrans.ITEMID = InventTransOrigin.ITEMID
where REFERENCECATEGORY = 0
group by InventTransOrigin.DATAAREAID , REFERENCEID , InventTrans.INVOICEID , InventTrans.ITEMID
) tt
where #DifferenceTable.DataAreaId = tt.DATAAREAID and #DifferenceTable.SalesId = tt.REFERENCEID
and tt.INVOICEID = #DifferenceTable.InvoiceId and tt.ITEMID = #DifferenceTable.ItemId
select * from #DifferenceTable`

Is there any way I could use Alternate for Lead() and Lag() Functions in SQL Server 2008?

I've table where I need to calculate difference between row to one underneath it and get the resultant to xml. it's daily task so i need it is kind of recursive task.
Structure for my current table is as below :
CREATE TABLE #Temp
(
, CurrentDateTime DateTime
, ID INT
, ThisYearToDateTotal INT
, ThisYearToDateCBT INT
, ThisYearToDateManual INT
, ThisYearToDateScanned INT
, InProcess INT
, InputRequired INT
)`
So far I've written the code as below :
SELECT
Today_CurrentDateTime
, Today_Total
, Today_CBT
, Today_Manual
, Today_Scanned
, Today_InProcess
, Today_InputRequired
, Yesterday_Total
, Yesterday_CBT
, Yesterday_Manual
, Yesterday_Scanned
, Yesterday_InProcess
, Yesterday_InputRequired
, (TD.Today_Total - YD.Yesterday_Total) AS Diff_in_Total
, (TD.Today_CBT - YD.Yesterday_CBT) AS Diff_in_CBT
, (TD.Today_Manual - YD.Yesterday_Manual) AS Diff_in_Manual
, (TD.Today_Scanned - YD.Yesterday_Scanned) AS Diff_in_Scanned
, (TD.Today_InProcess - YD.Yesterday_InProcess) AS Diff_in_InProcess
, (TD.Today_InputRequired - YD.Yesterday_InputRequired) AS Diff_in_InputRequired
FROM #YesterdayData AS YD
INNER JOIN #TodayData AS TD ON TD.Today_ID = YD.Yesterday_ID
and getting the output as below :
Now I've a restriction here that I can't create another permanent table and that's why I can't calculate difference for a each day for throughout a week.
Any Help ?
If the dates are input in order of the identity field ID then you can inner join with the same #temp table ON previous ID.
CREATE TABLE #Temp
( CurrentDateTime DateTime
, ID INT
, ThisYearToDateTotal INT
, ThisYearToDateCBT INT
, ThisYearToDateManual INT
, ThisYearToDateScanned INT
, InProcess INT
, InputRequired INT
)
INSERT INTO #Temp VALUES
('2017-11-14 07:50:25.230', 1, 400000, 50000, 20000, 30000, 1000, 700)
,('2017-11-15 07:50:25.230', 2, 460000, 53000, 26000, 38000, 2000, 1400)
,('2017-11-16 07:53:01.943', 3, 469692, 53904, 26755, 389033, 2026, 1489)
,('2017-11-17 07:53:01.943', 4, 469692, 53904, 26755, 389033, 2026, 1489)
DELETE FROM #Temp WHERE ID = 3
SELECT T.CurrentDateTime
, TPrev.ThisYearToDateTotal - T.ThisYearToDateTotal [Total Diff]
, TPrev.ThisYearToDateCBT - T.ThisYearToDateCBT [ThisYearToDateCBT Diff]
, TPrev.ThisYearToDateManual - T.ThisYearToDateManual [ThisYearToDateManual Diff]
, TPrev.ThisYearToDateScanned - T.ThisYearToDateScanned [ThisYearToDateScanned Diff]
, TPrev.InProcess - T.InProcess [InProcess Diff]
, TPrev.InputRequired - T.InputRequired [InputRequired Diff]
FROM #Temp AS T LEFT JOIN #Temp AS TPrev ON TPrev.ID = (SELECT MAX(T2.ID)
FROM #Temp T2
WHERE T2.ID > T.ID)
ORDER BY T.ID
--DROP TABLE #Temp
It's quite easy to mimic LAG and LEAD using sub queries.
For the #Temp table you have in your question, to get ThisYearToDateTotal value of the previous or next row (order by CurrentDateTime).
Here is a simple example:
SELECT ID,
CurrentDateTime,
ThisYearToDateTotal,
(
SELECT TOP 1 ThisYearToDateTotal
FROM #Temp as tLag
WHERE tLag.ID = tMain.Id -- partition by
AND tLag.CurrentDateTime < tMain.CurrentDateTime
ORDER BY CurrentDateTime DESC
) As Lag_ThisYearToDateTotal,
(
SELECT TOP 1 ThisYearToDateTotal
FROM #Temp as tLead
WHERE tLead.ID = tMain.Id -- partition by
AND tLead.CurrentDateTime > tMain.CurrentDateTime
ORDER BY CurrentDateTime
) As Lead_ThisYearToDateTotal
FROM #Temp as tMain

Increase the performance of an inventory (FIFO) query

My goal is to get the price from item which goes into stock and put the price into out item by (FIFO order by TranDate), then calculate the total price of any line of production (" lineid ").
This is what I have done
-- temp table for result
declare #Test table ( stockID int , OriQty decimal(16,2) ,inuse decimal(16,2) , price decimal(16,2) , lineid int , Inid int )
declare #StockIn table (ID int , StockID int ,qty decimal(16,2),Price decimal(16,2), tranDate Date , running int)
insert into #StockIn(ID , StockID , qty , Price , tranDate , running) values
(1,1 , 15 , 430 , '2014-10-09' , 1),
(2,1 , 10 , 431, '2014-12-09' , 2),
(3,1 , 15 , 432, '2015-02-02' , 3),
(4,2 , 15 , 450, '2014-08-05' , 1),
(5,2 , 6 , 450, '2014-10-09' , 2),
(6,2 , 15 , 452, '2015-02-02' , 3)
-- lineid = line production
declare #StockOut table (ID int , StockID int ,qty decimal(16,2), lineid int, tranDate Date)
insert into #StockOut(ID , StockID ,qty , lineid, tranDate )
values
(1,1 , 20 , 2, '2014-10-10'),
(2,1 , 10 , 4, '2014-12-20'),
(3,2 , 12 , 8, '2014-10-01'),
(4,2 , 3 , 8, '2014-10-01') ;
DECLARE #intFlag INT
SET #intFlag = 1 -- initial of loop
WHILE (#intFlag <= (Select Max(ID) from #StockOut) )
BEGIN
declare #stockID int
declare #ids table (ID int , Inuse decimal(16,2))
declare #lineid int
declare #qtyToRemove decimal(16,2) -- get qty from #StockOut
--get data from #StockOut row by row
select #stockID = StockID , #qtyToRemove = qty , #lineid = lineid from #StockOut where ID = #intFlag;
with cte as (
select *, sum(qty) over (order by tranDate ASC , qty DESC , tranDate ASC Rows UNBOUNDED PRECEDING) - #qtyToRemove
as Total FROM #StockIn Where stockID = #stockID )
-- running FIFO from #StockIn and update QTy when stock is running out
, RunningFIFO as (
select cte.StockID , cte.qty AS OriginalQty , Case when
case when 0 > total then cte.qty else cte.qty-total End > 0 then case when 0 > total then cte.qty else cte.qty-total End else 0 End As Inuse
, cte.Price , #lineid AS lineid , id
from cte
)
-- insert result into result table
insert into #test (stockID , OriQty ,inuse , cte.Price , lineid ,Inid ) OUTPUT inserted.Inid , inserted.inuse into #ids select * from RunningFIFO Where Inuse > 0
UPDATE #StockIn set qty = qty - inuse from #ids A inner join #StockIn B on A.ID = b.ID
SET #intFlag = #intFlag + 1
END
Select sum(inuse * price) AS total , lineid from #Test group by lineid
But when data are more than a thousand, this query runs super slow.
How could I increase the performance of this query?

Why this Where condition returns 0 Rows?

SELECT
*
FROM tblName
WHERE mode = '1' AND (category = #Category OR #Category = 'all' OR NewsId = #Category)
I passed #Category='all'. This returns 0 rows. If OR NewsId=#Category this condition not added, query will return all results
Try this one -
mode = '1'
AND
(
#Category = 'all'
OR
#Category IN (category, CAST(NewsId AS VARCHAR(10)))
)
Do not use too large data-type length (i mean MAX):
CREATE TABLE dbo.TBL_ContentsPage
(
NewsId INT IDENTITY(1001,1) NOT NULL PRIMARY KEY
, Header NVARCHAR(1024) NULL
, SmallImage IMAGE NULL
, TextContent NVARCHAR(2048) NULL
, PostedDate DATETIME NOT NULL DEFAULT(GETDATE())
, mode VARCHAR(50) NULL
, [status] VARCHAR(50) NULL
, category VARCHAR(200) NULL
, author NVARCHAR(1024) NULL
, imgRefID VARCHAR(50) NULL
)
ALTER PROCEDURE [dbo].[SPGetArticlePaging]
(
#startposition INT
, #stopposition INT
, #Category VARCHAR(200)
)
AS BEGIN
SELECT
NewsId
, Header
, TextContent
, author
, PostedDate
, category
, imgRefID
FROM (
SELECT
NewsId
, Header
, TextContent
, author
, PostedDate
, category
, DateRank = ROW_NUMBER() OVER(ORDER BY PostedDate DESC)
, imgRefID
FROM dbo.TBL_ContentsPage
WHERE mode = '1'
AND
(
#Category = 'all'
OR
#Category IN (category, CAST(NewsId AS VARCHAR(10)))
)
) t
WHERE DateRank BETWEEN #startposition AND #stopposition
RETURN 0
END

Trouble with OUTPUT statement. Incorrect Syntax

I am trying to update a data set based on one conditional and then retrieving all the updated rows. VS keeps telling me there is an incorrect syntax error near my OUTPUT clause but I do not see anything wrong. I am just trying to figure out how to use "OUTPUT" so this may be a very stupid mistake I am making but failing to see.
What is wrong (syntactically) with this OUTPUT clause?
CREATE PROCEDURE [dbo].[GetInitialSessionNotifications]
#CurrentSessionId bigint
AS
DECLARE #tempTable table(
id bigint NOT NULL,
[Type] nvarchar,
DocumentCommentID bigint,
AnnouncmentID int,
EventID int,
MeetingID int,
[Read] bit,
RecieverId int,
AnnouncmentCommentId bigint,
EventCommentId bigint,
MeetingCommentId bigint,
DateAndTime DateTime);
UPDATE Notifications SET SessionId = #CurrentSessionId
WHERE SessionId != #CurrentSessionId
OUTPUT INSERTED.id,
INSERTED.[Type],
INSERTED.DocumentCommentID,
INSERTED.AnnouncmentID,
INSERTED.EventID,
INSERTED.MeetingID,
INSERTED.[Read],
INSERTED.RecieverId,
INSERTED.AnnouncmentCommentId,
INSERTED.EventCommentId,
INSERTED.MeetingCommentId,
INSERTED.DateAndTime
INTO #tempTable;
SELECT id, [Type], DocumentCommentId, AnnouncmentID, EventID, MeetingID,
[Read], RecieverId, AnnouncmentCommentId, EventCommentId, MeetingCommentId, DateAndTime
FROM #tempTable;
RETURN 0
Try this one -
CREATE PROCEDURE [dbo].[GetInitialSessionNotifications]
#CurrentSessionId BIGINT
AS BEGIN
DECLARE #tempTable TABLE
(
id BIGINT NOT NULL ,
[Type] NVARCHAR ,
DocumentCommentID BIGINT ,
AnnouncmentID INT ,
EventID INT ,
MeetingID INT ,
[Read] BIT ,
RecieverId INT ,
AnnouncmentCommentId BIGINT ,
EventCommentId BIGINT ,
MeetingCommentId BIGINT ,
DateAndTime DATETIME
)
UPDATE Notifications
SET SessionId = #CurrentSessionId
OUTPUT
INSERTED.id ,
INSERTED.[Type] ,
INSERTED.DocumentCommentID ,
INSERTED.AnnouncmentID ,
INSERTED.EventID ,
INSERTED.MeetingID ,
INSERTED.[Read] ,
INSERTED.RecieverId ,
INSERTED.AnnouncmentCommentId ,
INSERTED.EventCommentId ,
INSERTED.MeetingCommentId ,
INSERTED.DateAndTime
INTO #tempTable
WHERE SessionId != #CurrentSessionId
SELECT id ,
[Type] ,
DocumentCommentId ,
AnnouncmentID ,
EventID ,
MeetingID ,
[Read] ,
RecieverId ,
AnnouncmentCommentId ,
EventCommentId ,
MeetingCommentId ,
DateAndTime
FROM #tempTable;
END