SSIS For Loop - Increment 'YYYYMM' by Month in Loop - sql-server

I am trying to execute a for loop that passes a begin date in the format like '201812' and goes up increments to an end date (as an example) of '201903'. The variables get passed as Integers to stored procs which then grab and insert data based on those values. I was trying to implement the pattern found here but it does not seem to be correctly incrementing:
SSIS For Loop Container with Date Variable
I have set up variables as follows:
The ETLBeginPeriod and ETLEndPeriod are set in Execute SQL Tasks here:
And then here are the expressions in the For Loop
The full expression in the AssignExpression is
#[User::Counter] = LEFT((DT_WSTR,19)(DATEADD("mm",1,(DT_DBDATE)(LEFT((DT_WSTR, 10) (#[User::Counter]),4) + "-" + RIGHT((DT_WSTR, 10) (#[User::Counter]),2) + "-" + "01"))),4) + SUBSTRING((DT_WSTR,19)(DATEADD("mm",1,(DT_DBDATE)(LEFT((DT_WSTR, 10) (#[User::Counter]),4) + "-" + RIGHT((DT_WSTR, 10) (#[User::Counter]),2) + "-" + "01"))),6,2)
When testing the AssignExpression the expression itself does return a correct value (i.e. it will change 201808 to 201809 but this doesn't seem to be getting hit. It will get the correct value on the initial pass and run 201808 and then try again with 201808. So it doesn't seem to change the Counter Value.

I think the main issue is that you forgot to cast the whole result as integer. Try using the following expression:
#[User::Counter] = (DT_I4)(LEFT((DT_WSTR,19)(DATEADD("mm",1,(DT_DBDATE)(LEFT((DT_WSTR, 10) (#[User::Counter]),4) + "-" + RIGHT((DT_WSTR, 10) (#[User::Counter]),2) + "-" + "01"))),4) + SUBSTRING((DT_WSTR,19)(DATEADD("mm",1,(DT_DBDATE)(LEFT((DT_WSTR, 10) (#[User::Counter]),4) + "-" + RIGHT((DT_WSTR, 10) (#[User::Counter]),2) + "-" + "01"))),6,2))

I figured this out - I decided to add a script task to view the variables and it turns out that they were incrementing correctly, but I had the wrong variable assigned to get passed to the stored procedure. I had originally been using the ETLBeginPeriod and forgot to change it to the Counter variable. Once I did that it worked. Arg.

Related

Cast (DT_TIMESTAMP) is not consistent from String to DateTime

I'm trying to convert an input of DT_WSTR to DT_TIMESTAMP on SSIS Derived column and when I do it the values do not match up, on one ocasion it recognizes the year correctly but on the other it think the day is the year
I tried to do
(DT_TIMESTAMP)((DT_WSTR,4)YEAR([Data Hora]) + RIGHT("0" + (DT_WSTR,2)MONTH([Data Hora]),2) + RIGHT("0" + (DT_WSTR,2)DAY([Data Hora]),2) + (DT_WSTR,10) Time_Column)
with no success
08-04-19 15:31:27 this is what I input and sometimes it recognizes the 19 as 2019 correctly but other times it thinks the 08 is the year so it puts 19/04/2008, I want the first one.
I expect to get the date correctly in dd/mm/yyyy hh:MM:ss.
Your question is not clear. In this answer I will try to fix the provided expression. Try using the following expression:
(DT_DBTIMESTAMP)((DT_WSTR,4)YEAR([Data Hora]) + "-" +
RIGHT("0" + (DT_WSTR,2)MONTH([Data Hora]),2) + "-" +
RIGHT("0" + (DT_WSTR,2)DAY([Data Hora]),2) + " " +
(DT_WSTR,10) [Time_Column])
Another suggestion is that, in cases where the date format is tricky (2 digit year part), it is better to use a script component to parse the date value since it provides more options using Date.ParseExact() function, as example:
Row.outDateColumn = DateTime.ParseExact(Row.inStringDate,"dd-MM-yy HH:mm:ss",System.Globalization.CultureInfo.InvariantCulture);

SSIS Variable Changing Time Component

I have a SSIS Variable named "DestinationDirectory" that has the following Expression:
#[User::SourceDirectory] + "\\" + REPLACE(SUBSTRING((DT_WSTR,35)((DT_DBTIMESTAMPOFFSET, 7) GETDATE() ),1,19),":","")
It returns for example:
C:\Finance Extract\2018-11-10 125913
I then have a heap of other variables such as the one below named "DestinationFileAdjustment" that work off "DestinationDirectory". It has the following expression:
#[User::DestinationDirectory]
+ "\\Adjustment_"
+ RIGHT("0" + (DT_STR, 2, 1252) DATEPART("dd" , GETDATE()), 2)
+ "_"
+ RIGHT("0" + (DT_STR, 2, 1252) DATEPART("mm" , GETDATE()), 2)
+ "_"
+ (DT_STR, 4, 1252) DATEPART("yyyy" , GETDATE())
+ ".csv"
What is supposed to happen is a file be created within that directory. The problem I'm experiencing is each time #DestinationDirectory is referred to, it is returning a different time value (e.g. C:\Finance Extract\2018-11-10 125914) and errors out because the directory does not exist.
Is there a way I can set that variable at run-time and it retain the same time value each and every time it is referred to?
Since you're using GETDATE() in your expression, I'm guessing that you're using the time that the package begins in the "DestinationDirectory" variable? If so, using the #[System::StartTime] system variable for the expression in this variable (example below) will provide this time and be consistent throughout the execution of the package.
#[User::SourceDirectory] + "\\" + REPLACE(SUBSTRING((DT_WSTR,35)((DT_DBTIMESTAMPOFFSET, 7) #[System::StartTime]),1,19),":","")
What I finished up doing to get around this was to have a Script Task and the following code within it:
Dts.Variables("User::DestinationDirectory").Value = Dts.Variables("User::SourceDirectory").Value.ToString + "\\" + Replace(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ":", "")
That hard coded the value for the variable nicely.

Convert an array of timestamps to seconds in Matlab

I'm new to SO and Matlab so please excuse any transgressions.
I'm trying to convert a seemingly simple array of timestamp strings to an equivalent array of seconds.
I wrote a this function:
% Function to calculate seconds from a timestamp in the following format:
% ddd hh:mm:ss.SSSS (example: 123 12:59:00.9999)
function a = TimestampToS(stamp)
% Uses the "named tokens" facility of MATLAB's "regexp" function.
expr = ['(?<ddd>\d+)' ... % ddd
' ' ... % Space " " separator
'(?<hh>\d+)' ... % hh
':' ... % Colon ":" separator
'(?<mm>\d+)' ... % mm
':' ... % Colon ":" separator
'(?<ss>\d+)' ... % ss
'.' ... % Dot "." separator
'(?<SSSS>\d+)']; % SSSS
parsedStamp = regexp(stamp, expr, 'names');
a = (str2double(parsedStamp.ddd) * 86400) + ...
(str2double(parsedStamp.hh) * 3600) + ...
(str2double(parsedStamp.mm) * 60) + ...
(str2double(parsedStamp.ss)) + ...
(str2double(parsedStamp.SSSS) * 0.0001);
It works great for an individual string:
>> TimestamptoS('123 12:59:00.9999')
ans =
1.067394099990000e+007
But if I try to use a cell array I get:
Attempt to reference field of non-structure array.
How can I get an array of seconds? I have tried all kinds of conversions of the input data and "parsedStamp" but nothing works. I don't understand Matlab or its matrix notation well enough. Any help gratefully received!
PS This is not a regexp question, no replies about regexp please!
You can do it very easily without modifying your function, by using cellfun. This essentially extracts each cell of the cell array and passes it to your function.
>> cellArray = {'123 12:59:00.9999','130 12:59:00.9999'}; % for example
>> cellfun(#TimestampToS,cellArray)
ans =
1.0e+007 *
1.067394099990000 1.127874099990000

What will be the DFA for the regular expression 0(0+1)*0+1(0+1)*1?

This is the DFA i have drawn-
Is it correct?
I am confused because q4 state has 2 different transitions for same input symbol which violates the rule of DFA, but I can't think of any other solution.
Your DFA is not correct.
your DFA is completely wrong so I don't comment
DFA for RE:
0(1 + 0)*0 + 1(1 + 0)*1
Language Description: if string start with 0 it should end with 0 or if string start with 1 it should end with 1. hence two final states (state-5, state-4).
state-4 : accepts 1(1 + 0)*1
state-5 : accepts 0(1 + 0)*0
state-1 : start state.
DFA:
EDIT :
+ Operator in Regular Expression
(0 + 1)* = (1 + 0)* that is any string consist of 1s and 0s, including Null string ^.
Here + means Union if it appear between two RE: and A U B = B U A (similarly)=> (0 + 1) = (0 + 1) .
meaning of plus + depends on syntax it appears in: If expression is a+ (+ is superscripted) this means one of more as, and If a+b then + means Union operation either a or b.
a+ : { a, aa, aaa, aaa.....} that is any number of a string in language with length > 1.
I think you should start with 0 first
0(1 + 0)*0 + 1(1 + 0)*1

SSRS: How to count true rows

I have a report with a dataset that has a column with booleans. In the table footer I want to display x / y where x is how many rows that were true and y is how many rows there was total.
Currently I have this:
=Count(Fields!Transfered.Value).ToString() + " / " + CountRows().ToString()
But the first becomes same as the last part. I then tried this:
=Sum(Fields!Transfered.Value).ToString() + " / " + CountRows().ToString()
But that generates an error, which I guess I can understand. I thought that if I converted the booleans into numbers where true is 1 and false is 0, then it could work out nicely. But how can I do that? Or is it a smarter way to do this all together?
Update: Have now also tried
=Sum(CInt(Fields!Transfered.Value)).ToString() + " / " + CountRows().ToString()
And got a negative result... O.o
Also found a way that worked, which I posted as an answer. But I won't accept it as an answer yet incase someone has a better way to do this =)
I can tell you why things went wrong...
Count(Fields!Transfered.Value) is simply the number of rows. aka CountRows()
Sum(Fields!Transfered.Value) is trying to aggregate "true" or "false" = error
Sum(CInt(Fields!Transfered.Value)) will sum -1 and 0 because VB.NET true = -1
Sum(IIF(Fields!Transfered.Value, 1, 0)) fixes the sign issue = your solution
To avoid the extra IIF, you could use negate the sum of all the -1s
= -Sum(CInt(Fields!Transfered.Value)).ToString() + " / " + CountRows().ToString()
In the end, either solution would be OK and both are equally kludgy
Figured out a way to do it, although there is probably a better more clear and logical way...
=Sum(IIF(Fields!Transfered.Value, 1, 0)).ToString() + " / " + CountRows().ToString()
I came across this today and at least verified that I wasn't the only one that got a negative sum value for bools out of SSRS. Thanks.
My solution was to use ABS for absolute value. I like that better than just negating the expression solely because it's easier to see visually where the '-' might be missed if you're not careful in reading the expression.
but it's essentially the exact same thing
Here is a way where you count on a grouped value
=CountDistinct(IIF(Fields!TrueOrFalseField.Value,
Fields!GroupedField.Value,
"BadValueToBeRemovedFromCount"))
-IIF(CountDistinct(Fields!TrueOrFalseField.Value)=1
and First(Fields!TrueOrFalseField.Value)
, 0, 1)
The second part
-IIF(CountDistinct(Fields!TrueOrFalseField.Value)=1
and First(Fields!TrueOrFalseField.Value)
, 0, 1)
remove 1 from the count if it has True and False value or if there are only one distinct false value.

Resources