Set Date from another table in SQL Server - sql

I have a code in VB.Net application which I would like to move to stored procedure.
VB code looks something like this :
if(id == 3)
{
var year = Year(invoiceDate)
updatedDate = DateSerial(dueYear, DueDateMonth, DueDateDay)
If updatedDate < invoiceDate Then
updatedDate += 1
updatedDate = DateSerial(updatedDate , getMonthFromDBTable, getDayFromDBTable)
End If
}
This is part of a condition which I am trying to resolve.
Currently in SQL I have the following
DECLARE #tmpCalendarDate DATETIME;
DECLARE #tmpYear int;
SET #tmpCalendarDate = convert(varchar(10), getdate(),120);
SET #tmpYear = DATEPART(yyyy, #tmpCalendarDate);
SELECT COALESCE (
CASE WHEN tt.ID = 1 THEN DATEADD(day, t.DaysUntilDue, r.InvoiceDate) END,
CASE WHEN tt.ID = 3 THEN -- This is where I need to add the condition.
I was thinking of setting the #tmpCalendarDate with the values to look something like
CASE WHEN tt.ID = 3 THEN #tmpCalendarDate = '#tmpYear-t.DueDateMonth-t.DueDateDay'
where t is a table.
This value cannot be changed, so I would rather calculate and fetch it once rather than calculating it every time binding changes (wpf application).
Any help is greatly appreciated.
UPDATE: I realized maybe I am vague with my question, so here it is
How do i set #tmpCalendarDate? I tried
SELECT #tmpCalendarDate = '#tmpYear-t.DueDateMonth-t.DueDateDay' FROM table t
and I get an error 'Conversion failed when converting date and/or time from character string.' Instead I am expecting something like #tmpCalendarDate to be set to '2016-03-12'
Also, can I add an If..Else condition inside CASE.Then
In my example:
CASE WHEN tt.ID = 3 THEN #tmpCalendarDate = '#tmpYear-t.DueDateMonth-t.DueDateDay'
IF (#tmpCalendarDate > InvoiceDate)
BEGIN
--Do some logic
END
ELSE
--Do some logic
BEGIN
END

You can use DATEFROMPARTS
#tmpCalendarDate = DATEFROMPARTS(#tmpyear, t.DueDateMonth, t.DueDateDay)
Your mistake in your original attempt is you are setting #tempCalendarDate to actual string #tmpYear-t.DueDateMonth-t.DueDateDay which results in a conversion error.

Related

How to get rid of Cursor and use UPDATE with SELECT

I believe that the cursor used in this code is the reason for some major performance issues, however I am new to TSQL.
Following script runs on SQL SERVER 2008. I am trying to redo it so I use JOIN statements instead, however I have not been able to do so successfully.
DECLARE AIRAMSDET CURSOR FOR
SELECT BILL, RECIEPT, NAME
FROM Client_Table
WHERE IsProcessed = 1
AND TYPE IN ('Sub','First_Time','Old') AND LEN(BILL) > 1
OPEN AIRAMSDET
FETCH AIRAMSDET into #VARBILL, #VARRECIEPT, #VARNAME
WHILE ##Fetch_Status = 0
BEGIN
UPDATE archieve
SET entry = left(#VARBILL + '- '+ #VARNAME)
WHERE archiveID = #VARBILL
END
It should be something like following
UPDATE ARCHIEVE
SET ENTRY = CT.BILL + '-' + CT.NAME
FROM CLIENT_TABLE CT
WHERE
ARCHIEVE.ARCHIVEID = CT.BILL
AND CT.ISPROCESSED = 1
AND CT.TYPE IN ('Sub','First_Time','Old') AND LEN(BILL) > 1
I have not included LEFT() as its use in your query wasn't very clear. Left takes an integer_expression as its second parameter while you are passing ##VARNAME which most likely is a VARCHAR. Please add that as you deem fit.

MSSQL Stored Procedure with dynamically added WHERE?

I have this Stored Procedure, where i need to check if #DateChk == 1, THEN i want to add a WHERE-clause to the SQL statement in the SP. If its 0, there should not be any WHERE-clause.
How do i script such function? In a program i could just build in the string to pass to the server, but i have not found any way to do this in the SQL server.
SELECT dateDay, SUM(nok) as NOK, SUM(ok) as OK, (SUM(ok) + SUM(nok)) as 'Total'
FROM #st
SELECT CASE #DateChk
WHEN 1: WHERE dateDay BETWEEN '2016-08-01' AND '2016-08-31'
Something like this, if #DateChk = 1, the WHERE should be added, else fetch all records.
You can modify your condition like this:
SELECT dateDay, SUM(nok) as NOK, SUM(ok) as OK, (SUM(ok) + SUM(nok)) as 'Total'
FROM #st
WHERE
(#DateChk = 1 and (dateDay BETWEEN '2016-08-01' AND '2016-08-31'))
or #DateChk = 0
And it will exactly match your desired behaviour: condition on dateDay will be applied only when #DateChk = 1.

Condition WHERE clauses inside stored procedure

I am working with a stored procedure where I want to add or remove WHERE clauses according to the values of a couple parameters.
This is what I've got so far:
WHERE
t.iDdPais = #iIdPais
AND t.iIdRegion = #iIdRegion
AND t.dtFecha BETWEEN #dtStart AND #dtEnd
BUT, if #iIdPais is 0 (which means ALL), I need to remove that clause from the WHERE statement, the same goes to #iIdRegion.
Put the entire SELECT inside IF clause..
IF(#ildPais =0 AND #ildRegion =0)
SELECT <THE DATASET> FROM THE TABLE
WHERE
t.iDdPais = #iIdPais
AND t.iIdRegion = #iIdRegion
AND t.dtFecha BETWEEN #dtStart AND #dtEnd
ELSE
SELECT <THE DATASET> FROM THE TABLE
--no where clause
You just need to use normal boolean logic:
WHERE
(#iIdPaid = 0 OR t.iDdPais = #iIdPais)
AND (#iIdRegion=0 OR t.iIdRegion = #iIdRegion)
AND t.dtFecha BETWEEN #dtStart AND #dtEnd

MSSQL 2008: Problems with the 'Case' - statement

I'm having some troubles finding a solution to my SQL-Problem. I've tried google but so far my search didn't give me any statisfactory results.
I have an SSRS report with two parameters:
#SupplierId NVARCHAR (May contain NULL)
#EmployeeId NVARCHAR (May contain NULL)
My original query retrieved all the employees who came in service during the last year:
SELECT Name, Surname from dbo.Employee Where Employee.DateInService > DATEADD(year,-1,GETDATE())
Right now i want to add those parameters to the query using the following logic.
Remark this is pseudo SQL:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
IF (LEN(RTRIM(#SupplierId)) = 0 Or #SupplierID IS NULL ) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
My search sofar led me to the Case statement. I made a query which contains an syntax error (obviously). My base query:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
Error: Syntax error near '='.
Question 1: Why does he give an error near the '='?
Question 2: How do i correctly implement the following:
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0 "Or #SupplierId is null" ) THEN
Instead of
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) Then dbo.Employee.EmployeeId = #EmployeeId
WHEN (#SupplierId IS NULL) Then dbo.Employee.EmployeeId = #EmployeeId
ELSE dbo.Employee.EmployeeId = #EmployeeId END
Note: if i've missed a post during my google searches, please don't hesitate to point it out.
Thanks for your help
You can't change the actual query predicate like that with CASE - there are 2 distinct queries depending on the value of #SupplierId. You can conditionally apply the filter as follows (I've assumed the #SupplierId = null flow is the same as the whitespace branch:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE())
AND
(
(dbo.Employee.EmployeeId = #EmployeeId
AND (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL))
OR
(dbo.Employee.SupplierId = #SupplierId AND LEN(RTRIM(#SupplierId)) > 0)
)
Although this can be prone to query plan sniffing related performance issues, in which case you might need to consider an alternative approach, e.g. using parameterized dynamic sql to build up and execute the sql, as there are 2 distinct process flows through the query.
Edit
As per Ypercube's comment above, in order to provide the boolean result needed for the predicate, if you can find a hack workaround is to find a way to project a COMMON scalar from each of the CASE .. WHEN row and then do a comparison of the scalar. In the example below, projecting a yes / no flag.
SELECT * FROM dbo.Employee
WHERE
CASE
WHEN (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL)
THEN CASE WHEN dbo.Employee.EmployeeId = #EmployeeId THEN 1 ELSE 0 END
ELSE CASE WHEN dbo.Employee.SupplierId = #SupplierId THEN 1 ELSE 0 END
END = 1;
But the big problem with this approach is performance - the above will require a full scan to determine the results.

Conversion from nvarchar to float isn't working

I am unable to get the following query to work due to errors upon conversion from nvarchar to float; I need to convert theData field to float in order to round it, but the data is originally an NVARCHAR(20) because the column holds character data as well. I've tried casting each of the instances of theData to float but it still didn't work, can anyone tell me what I'm missing?
UPDATE tblData SET tblData.theNumericData = CASE WHEN IsNumeric([theData]) = 1
THEN Round(Convert(float, [theData]),(Len([theData])-Charindex('.',[theData])))
ELSE Null END
WHERE tblData.theFlag =1;
I have tried the following two variants...
UPDATE tblData SET tblData.theNumericData = CASE WHEN IsNumeric([theData]) = 1
THEN Round(Convert(float, [theData]),(Len(Convert(float, [theData]))-
Charindex('.',Convert(float, [theData]))))
ELSE Null END
WHERE tblData.theFlag =1;
and...
UPDATE tblData SET tblData.theNumericData = CASE WHEN IsNumeric([theData]) = 1
THEN Convert(nvarchar(20),Round(Convert(float, [theData]),(Len(Convert(float,
[theData]))- Charindex('.',Convert(float, [theData]))))) ELSE Null END
WHERE tblData.theFlag =1;
Can't answer the question because we don't know the error you're getting but... you should move the case to where... it'll make it more readable.
UPDATE tblData
SET tblData.theNumericData = Convert(float, [theData])
WHERE IsNumeric([theData]) = 1 AND tblData.theFlag =1;