Expressions out of an SQLExecute Task - sql

I have an Execute SQL Task that compares 2 snapshot dates and if the date is greater than a month it returns a 1 else it returns a 0. If I use an expression to test for one of the expression I get an advancement in the project however if I test for the other I get no return and the process stops. I have not changed the data so it is testing the same data set. The following are my expression testing:
#[User::MonthFlag] =="1"
#[User::MonthFlag] =="0"
The month Flag is what I am using to pass out as my result set. Heres the query I used:
if (datediff(mm,#maxdw01,#maxas48)=1)
begin
select 1 as MonthFlag
end else
select 0 as MonthFlag
End

Related

Error iterating a Multi Value Parameter in SSRS Custom Code

I have a Multi value parameter in SSRS 2016 populated by a dataset. I have set the parameter properties as follows Data type 'Date/time', 'Allow multiple values', visibility is Internal and I've pointed Available and Default values to my dataset which is a simple select query returning dates. Using a for loop in custom code, I want to check if a given date is equal to any of the dates in the parameter. Whenever I use the index in the For Loop to index the parameter value I get #Error however
when I hard code the index with a any number I get the desired result
While (dt < endDate)
For i As Integer = 0 To Report.Parameters!parameter.Count()
If Report.Parameters!parameter.Value(i) = dt Then
count = count +1
Exit For
End If
Next i
dt = dt.AddDays(1)
End While
I expect 1 to be added count every time there's a match

SQL: Replacing dates contained within a text string

I am using SQL Server Management Studio 2012. I work with medical records and need to de-identify reports. The reports are structured in a table with columns Report_Date, Report_Subject, Report_Text, etc... The string I need to update is in report_text and there are ~700,000 records.
So if I have:
"patient had an EKG on 04/09/2012"
I need to replace that with:
"patient had an EKG on [DEIDENTIFIED]"
I tried
UPDATE table
SET Report_Text = REPLACE(Report_Text, '____/___/____', '[DEIDENTIFED]')
because I need to replace anything in there that looks like a date, and it runs but doesn't actually replace anything, because apparently I can't use the _ wildcard in this command.
Any recommendations on this? Advance thanks!
You can use PATINDEX to find the location of Date and then use SUBSTRING and REPLACE to replace the dates.
Since there may be multiple dates in the Text you have to run a while loop to replace all the dates.
Below sql will work for all dates in the form of MM/DD/YYYY
WHILE EXISTS( SELECT 1 FROM dbo.MyTable WHERE PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text) > 0 )
BEGIN
UPDATE t
SET Report_Text = REPLACE(Report_Text, DateToBeReplaced, '[DEIDENTIFIED]')
FROM ( SELECT * ,
SUBSTRING(Report_Text,PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text), 10) AS DateToBeReplaced
FROM dbo.MyTable AS a
WHERE PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text) > 0
) AS t
END
I have tested the above sql on a dummy table with few rows.I don't know how it will scale for your data but recommend you to give it a try.
To keep it simple, assume that a number represents an identifying element in the string so look for the position of the first number in the string and the position of the last number in the string. Not sure if this will apply to your entire set of records but here is the code ...
I created two test strings ... the one you supplied and one with the date at the beginning of the string.
Declare #tstString varchar(100)
Set #tstString = 'patient had an EKG on 04/09/2012'
Set #tstString = '04/09/2012 EKG for patient'
Select #tstString
-- Calculate 1st Occurrence of a Number
,PATINDEX('%[0-9]%',#tstString)
-- Calculate last Occurrence of a Number
,LEN(#tstString) - PATINDEX('%[0-9]%',REVERSE(#tstString))
,CASE
-- No numbers in the string, return the string
WHEN PATINDEX('%[0-9]%',#tstString) = 0 THEN #tstString
-- Number is the first character to find the last position and remove front
WHEN PATINDEX('%[0-9]%',#tstString) = 1 THEN
CONCAT('[DEIDENTIFIED]',SUBSTRING(#tstString, LEN(#tstString)-PATINDEX('%[0-9]%',REVERSE(#tstString))+2,LEN(#tstString)))
-- Just select string up to the first number
ELSE CONCAT(SUBSTRING(#tstString,1,PATINDEX('%[0-9]%',#tstString)-1),'[DEIDENTIFIED]')
END AS 'newString'
As you can see, this is messy in SQL.
I would rather achieve this with a parser service and move the data with SSIS and call the service.

Return Error if query returns no results

I am creating a SQL job using the OPENROWSET function to export data from a view to excel.
I was just wondering if there was a way to have a the query return an error if there is are no rows of data returned, even though the query itself is executing correctly.
What i am looking for is a way where if the query below were to return 0 rows of data, the execution would return an "Error" result. Whereas if it returned 1 or more rows of data, it would execute normally.
CustSalesBreakdown is a view i have created, which brings in sales by customer, grouping it by month/year. As "Total" is a decimal value, I cast it as float for sorting it accordingly.
INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 8.0;Database=E:\Reports\CustSalesBreakdownTest.xls;',
'SELECT * FROM [Test$]')
SELECT
[Account],[Ref#],[CustomerName],[Phone],[Rep],[Period-MTD]
,[Invoices],[Credits],[Total],[FilterDate]
from custsalesbreakdown
where datediff(month,[FilterDate],getdate())=0 and [Rep] = '18'
order by cast([Total] as float) Desc;
This query executes successfully, however it returns no data, due to there being no data to return at that time.
The reason for this is that if it returns no rows of data, i want the job to proceed to a different step (On failure - Go to Step X), otherwise if it had returned values (On Success - Go to Step Y).
SamC
Dividing by zero always throws an error.
select 1/count(*) from table where column = 'something'

How do i "skip" a row if there is a failure on a sql function

I want to create a stored procedure in sql server which will allow me to skip the row and move on to the next row when an error is encountered. For example, when i pass in an input of 'BOZ3C 51' it works, but fails with the error - 'Invalid length parameter passed to the LEFT or SUBSTRING function.' when it encounters an input of 'C Z3C'
BEGIN TRY
select distinct LEFT(SUBSTRING(ticker,1,CHARINDEX(' ',ticker) -1),len(SUBSTRING(ticker,1,CHARINDEX(' ',ticker) -1))-3)as CLASS
from SECURITY
SET #RETMSG = 'SUCCESS'
END TRY
BEGIN CATCH
SET #RETMSG = 'SecClass ERRNUM: ' + CONVERT(VARCHAR, ERROR_NUMBER()) + ' SecClass ERRMSG: ' + ERROR_MESSAGE();
print #RETMSG
END CATCH;
How can i handle such situations? Thanks for the pointers.
The only way to guarantee that you avoid the error in SQL Server is to use the case statement. SQL Server reserves the right to rearrange operations . . . and this means that the calculation in the SELECT might happen before the filtering in the WHERE.
select distinct (case when len(SUBSTRING(tinker,1,CHARINDEX(' ',tinker) -1)) >= 3
then LEFT(SUBSTRING(ticker,1,CHARINDEX(' ',ticker) -1),len(SUBSTRING(ticker,1,CHARINDEX(' ',ticker) -1))-3)as CLASS
end) -- if not appropriate format, then return `NULL`
from SECURITY;
case is in general guaranteed to evaluate the when clauses in order and before the then (there are exceptions involving aggregated functions, but they do not apply in this case).
You can add a where clause that filters out rows that will fail.
where len(SUBSTRING(tinker,1,CHARINDEX(' ',tinker) -1)) - 3 >= 0
The best solution would to make everything more programtic. The issue is that you are checking how many characters are before a space, then subtracting 3. If you can calculate a number instead of substracting 3 every time and avoid going below 0, that would solve the errors.

Can I return a string based on a value in the table?

Consider the following query:
SELECT operation, [...] FROM tableName
The operation field will retrieve an integer from 1 to 4. What I would like to do is assign a string value to a variable in the SQL query, based on the integer value of operation.
If it were up to me, I would have a corresponding table that contained the name of each operation, in which case a JOIN would pick up the operation string. Unfortunately, I do not control the database.
I don't know if this is even something SQL can do, and I could certainly iterate over the returned data using PHP to perform this task instead, but it makes sense to do it all in one hit if possible.
Try something kile this:
SELECT
CASE
operation
WHEN 1 THEN 'OP1'
WHEN 2 THEN 'OP2'
WHEN 3 THEN 'OP3'
WHEN 4 THEN 'OP4'
ELSE
'Unknown OP'
END OperationName
,
[...] FROM tableName
select
case when operation = 1 then
'1st operation'
case when operation = 2 then
'2nd operation'
else
'Unknown operation'
end operation_name
from tableName