Split string from a string SQL Server 2008 - sql-server-2008

I would like to take value from a string. Please see this example string format: "(Fault Reported: Not Heating - POD - CC - We fit shower 2 years ago - Lime - €124.00 ) ( Job Report: Replaced Element & Stat. €149.00 paid CC 08/17)"
I would like to select second parentheses value
`(Job Report: Replaced Element & Stat. €149.00 paid CC 08/17)`
How could I achieved that? I tried below way but can't get the actual value.
DECLARE #s VARCHAR(max)='(Fault Reported: Not Heating - POD - CC - We fit shower 2 years ago - Lime - €124.00 ) ( Job Report: Replaced Element & Stat. €149.00 paid CC 08/17) '
SELECT PARSENAME( REPLACE(#s,') (','.'),2)

PARSENAME() is not the best choice here because there are other <unknown number> of . characters, which would need to be replaced first and then put back after, which gets messy fast.
How about:
DECLARE #s varchar(max) = '(Fault Reported: Not Heating - POD - CC - We fit '
+ 'shower 2 years ago - Lime - €124.00 ) ( Job Report: Replaced Element '
+ '& Stat. €149.00 paid CC 08/17) ';
SELECT SUBSTRING(#s, CHARINDEX(') (', #s) + 2, 8000);
Result:
( Job Report: Replaced Element & Stat. €149.00 paid CC 08/17)
One example is almost never enough to provide the right solution, though. Lots of edge cases you probably haven't considered yet. The most glaring:
What if there is only one set of parentheses? Do you want NULL, empty string, something else?
What if there are more than two? Do you want everything 2+? Only the 2nd? Only the last? Something else?

Related

How to use expression builder to create a file name with date even for the first day of the month

I have an SSIS package that runs each morning to pull the previous days file from an FTP server. I am using the code below to create the file name using the previous date. Everything works great with this except when today's date is the first day of the month. for example, if ran today (3/1/2021) this returns name_of_file_20210328.xml.gz, however yesterday's date is 2/28/2021 not 3. How do i update this to say if today's date is beginning of month return mm - 1?
"name_of_file_" + (DT_STR,4,1252)(DATEPART("yyyy",GETDATE())) + (LEN((DT_STR,2,1252)(DATEPART("MM",GETDATE()))) == 2 ? (DT_STR,2,1252)(DATEPART("MM",GETDATE())) : "0" + (DT_STR,2,1252)(DATEPART("MM",GETDATE()))) + (LEN((DT_STR,2,1252)(DATEPART("dd",DATEADD( "day",-1, GETDATE())))) == 2 ? (DT_STR,2,1252)(DATEPART("dd",DATEADD( "day",-1, GETDATE()))) : "0" + (DT_STR,2,1252)(DATEPART("dd",DATEADD( "day",-1, GETDATE())))) +
".xml.gz"
Create a variable, Yesterday of type DateTime. Specify that it uses an expression and use the following expression. This provides a consistent reference point you can test against and if you disable the expression, allows you to specify a date for boundary/special case checking (like a leap year 2020-03-01)
DATEADD("DAY", -1, #[System::StartTime])
The next steps, especially if you're starting out, is to build the date parts in separate variables. It doesn't cost any extra to use lots of variables in your package and makes troubleshooting so much easier.
Add a new variable, YearString of type String.
(DT_WSTR, 4)datepart("YYYY", #[User::Yesterday])
That was easy.
Now we need to deal with create a zero, left padded string. Right now, your expression looks like it's trying to determine if day or month has 2 digits. I have a cleaner expression.
We're going to convert the day/month to a string and then prepend a zero to it. For Jan-Sep, we'll end up with a 2 character expression, Oct-Dec, we'll have a three character expression e.g. 011. For Day, similar bit where it's 01-09 or 010-031. We will then take the last two characters from the string. For the two character strings, it's a no-operation and for the three character variant, it gets us what we want.
Add Variable MonthString, as type string, to your package
RIGHT("0" + (DT_WSTR, 2)datepart("MONTH", #[User::Yesterday]), 2)
Add Variable DayString, as type string, to your package
RIGHT("0" + (DT_WSTR, 2)datepart("DAY", #[User::Yesterday]), 2)
Take a moment and look at your Variable collection. You can see that you have all the building blocks needed to properly construct your YYYYMMDD string. If something is wrong, it's small enough snippet to play with it. If not, break it up into smaller Variables.
Now that we have defined #Yesterday and then built YearString, MonthString and DayString off of Yesterday, all we have to do is bring it all together with the concatenation + operator
Back to the Variable well, creating #CurrentFileName of type string
"name_of_file_" + #[User::YearString] + #[User::MonthString] + #[User::DayString] + ".xml.gz"
Results in a value of name_of_file_20210216.xml.gz
Not addressed in this answer but things you should think about
What happens when the job doesn't run at all today (server fails horrifically, the data source is down, etc)? To pick up and process 2 days ago file, you would need to edit this package, run it through whatever change review process is applicable, deploy to prod, run it and then go back to the process yesterday file package.
That's not fun to type much less consider. You certainly aren't going to change the server time to trick the expression into being yesterday.
I am an advocate for passing the run date to the package (mechanism depends on how you deploy/run packages). In that situation, it's been my experience that it's a far easier bureaucracy fight to change the calling parameter (because no "code" has changed) than to get an emergency code change run through.

Ms-Access DLookup - how to I return only records from this year?

I think this should be simple, but I've been struggling for too long.
I have a form with a bound text box which I would like to return a value it has calculated. It calls on the table 'Training' which stores the variables Client, Standard and Date. Client is a string, standard is an integer and Date is in the format dd/mm/yyyy. I would like the box to return the sum of the Standard entries for this year.
So, if we've been out to see Client A last week and done one session and been out again today and done two, the table might look like:
Client A - 1 - 01/01/2017 <br/>
Client A - 1 - 12/01/2018 <br/>
Client A - 2 - 17/01/2018 <br/>
Client B - 1 - 15/01/2018
I'd like my box to return the value '3', ignoring Client A's training last year or the training this year of any other client.
I can get the box to correctly distinguish between clients, but not between years using this code:
=DSum("[Standard]","Training","[Client] = '" & [Client] & "'")
That selects the client from the training table, based on the client record currently selected in the form. It sums all the training that client has ever had - so in the example above returns '4'.
What I am struggling with is how to restrict the year. I've tried a number of variations on:
& "Year([TrainingDate])=#" & Year(Date())
but always get either Name? or Error. What am I doing wrong?
With thanks,
Matt
Use:
=DSum("[Standard]","Training","[Client] = '" & [Client] & "' And Year([TrainingDate]) = Year(Date())")
year is an integer -- try Year([TrainingDate])= " & Year(Date())

SSRS 2008 - How to link 2 or more year parameters into 1

After some research, I see that blending parameters is a popular topic but I haven't found a solution to this specific situation. Shortly said, I have 3 parameters from various datasets all stating the same year and I want to blend them (visually) into 1 so to eliminate this redundancy for my report's end-user.
In the "Available values" from "Parameter properties", all the values are taken from a dataset (hidden) and the "value field" is [Measures].[ParameterValue] from their corresponding hidden dataset.
When I "show hidden datasets" and go into "text mode" of each of these hiden datasets are these are the 3 MEMBER [Measures].[ParameterValue] AS :
[Time].[Financial Year].CURRENTMEMBER.UNIQUENAME
[Financial Period].[FP - Year].CURRENTMEMBER.UNIQUENAME
[Time exit].[Financial Year Exit].CURRENTMEMBER.UNIQUENAME
When you look at what value this gives, they have the following output (accordingly):
[Time].[Financial Year].&[2017]
[Financial Period].[FP - Year].[FP - Year].&[2017]
[Time exit].[Financial Year Exit].Financial Year Exit].&[2017]
A. So, in my opinion, since the "roots" of each [Year] parameter value are different I need to create a dataset or a member within each of these hidden datasets that replaces this [2017]. Is that "doable" and, if yes, any guidance on how?
B. If not, another outcome would be acceptable as well: the end user would need to generate mostly current year and current year-1. To tackle this I made a Template "Year" DS with the same content as in FP - Year and added the following members:
Member [Measures].[Last Year] as 'YEAR(NOW())-1'
Member [Measures].[Current Year] as 'YEAR(NOW())'
I inserted them into SELECT and previewed, it displays 2 new columns with 2017 and 2016. Then I went and changed in that PF-Year parameter's DS, value and label and I get an error. Any suggestions?
Any suggestions on this?
EDIT1: I have tackled B. and found a solution to it, I simply created the following 2 Default values for each parameter:
Current year: ="[Time].[Financial Year].&[" + CStr(Year(Now())) + "]"
Last year: ="[Time].[Financial Year].&[" + CStr(Year(Now())-1) + "]"
However, even though with this result I presume it will minimize the number of actions for the end-user, I would still prefer having 1 parameter showing instead of 3...
EDIT2 & partial solution I found another solution for A., it's not exactly what I wanted but it kind of gets the job done.
Created a new Year parameter with 2 available values: [CurrentYear] and [LastYear]
For each of the default values of each other parameter, I swaped the 2017 and 2016 values for CStr(Parameters!Year.Value(0)) and for CStr(Parameters!Year.Value(1)) accordingly. Example: ="[Year exit].[Financial Year exit].&[" + CStr(Parameters!Year.Value(0)) + "]".
In the options of each parameter, I set them as "Hidden" expect for my new Year parameter.
Now, I have 1 Year parameter with a dropdown list displaying Current Year and Last Year.
Even though this alleviates the issue, is there anyway to have a similar outcome but with the drop down menu displaying the actual years? i.e. it would be dynamic so in years to come, there would be 2018, 2019, etc. that would pop up? This way the end user would be able to compare not only current and past year but any 2 years?
Thanks to all!
EDIT3 Here is a screen shot of where I am at, at this point:
EDIT4
I have arrived to a fix: since I know that the end-users will only be comparing 2 years at a time (so 2 default values per parameter), I left hidden 2 parameters out of 3 and for the 2 hidden, I changed their default values.
So, I kept #[Financial Year] as my main parameter and the others have the following default values:
#[FP - Year]:
="[Financial Period].[FP - Year].[FP - Year].&[" + CStr(Parameters!Financial Year(0)) + "]"
="[Financial Period].[FP - Year].[FP - Year].&[" + CStr(Parameters!Financial Year(1)) + "]"
#[Financial Year exit]:
="[Year exit].[Financial Year exit].&[" + CStr(Parameters!Financial Year(0)) + "]"
="[Year exit].[Financial Year exit].&[" + CStr(Parameters!Financial Year(1)) + "]"
And voilà the result:
I'd suggest two ways:
1: SSRS: add an invisible parameter (i.e. CurrentYear) and run in your MDX query the following:
StrToMember('[Time].[Financial Year].&[' +#CurrentYear + ']')
2: MDX: add a dynamic calculated members for each hierarchy:
member [Time].[Financial Year].[Current Year] as
StrToMember('[Time].[Financial Year].&[' + Format(Now(),'yyyy') + ']')
See my blog post for more details.

ColdFusion DateDiff - Is there a better way?

I simply want to combine the total years of service from various members of my team. The below script works fine, however, the hire date for each member does not pull from a database. Which means I have to hard code each persons hiredate and then do a DateDiff on them. With a team of 28 members that would cause a code management nightmare.
My main goal is to make the code simpler and more efficient, especially when managing 28 team members. If part of the path requires adding the user's hiredate to a database; I can do that. I just see the code below needing a rewrite, I just don't know the best method.
Is there a better way?
<cfscript>
REQUEST.rightnow = Now();
dateBob = DateDiff("yyyy", "1996 02 01", REQUEST.rightnow);
dateSam = DateDiff("yyyy", "1996 08 01", REQUEST.rightnow);
dateJoe = DateDiff("yyyy", "2004 12 01", REQUEST.rightnow);
dateJohn = DateDiff("yyyy", "2001 01 01", REQUEST.rightnow);
combinedDate = (dateBob + dateSam + dateJoe + dateJohn);
</cfscript>
<cfoutput>
#combinedDate# total years<br>
#dateBob# years<br>
#dateSam# years<br>
#dateJoe# years<br>
#dateJohn# years<br>
</cfoutput>
--- EDIT ---
Per Matt's suggestion as a database query; something like this?
SELECT hire_date,
ROUND((DATEDIFF(NOW(),hire_date)) / 365) AS dateDiff
FROM members
WHERE hire_date IS NOT NULL
--- EDIT 2 ---
I just realised I forgot to add SUM() of all the "dateDiff". If anyone uses this SQL you will have to hand it off to ColdFusion, I suppose. Unless I overlooked a way to do it in SQL?
--- EDIT 3 ---
Per Leigh's comments of encouragement; I found a better way. The TIMESTAMPDIFF() MySQL function adds a unit variable that can be day, month, year, etc. This allowed me to remove the / 365 and the ROUND(). Which in turn allowed me to use SUM() and not get a syntax error from MySQL. I also renamed my alias from dateDiff to just Dif because I wanted to avoid confusion with DATEDIFF().
See below. :D
SELECT hire_date,
SUM(TIMESTAMPDIFF(YEAR,hire_date,NOW())) AS Dif
FROM members
WHERE hire_date IS NOT NULL
The solution to improving the code posted for ColdFusion was actually replacing it. By adding the hire_dates of each member to an existing MySQL database and writing the query below; I no longer needed all of the ColdFusion code in my original post.
SELECT SUM(TIMESTAMPDIFF(YEAR,hire_date,NOW())) AS Dif
FROM members
WHERE hire_date IS NOT NULL

How to iterate over table in Access 2010

I would like to iterate over the rows in my Payment table. User chose for what month and year has wants to book and I want to check in the each raw if this house was booked for this year and month. I want to compare if
HouseID == chosenHouseID && BookingMonth == chosenBookingMonth &&
BookingYear==chosenBookingYear.
If this is true it should pop out message box with info that house was already booked for this month. Also if user chose more than one month i.e. numMonths would be 3, it should increment value of the month (which is a text) it should go to the next value (if there is no next value then it should do mod 12) and do the checking again. Maybe it will be necessary to switch data type of BookingMonth to numeric?
However I hope I was clear what I want to do. I have experience with Java, C, Python and Visual Basic, but I did not do much in Access so it is quite confusing. I could not find the any useful info how to perform this operation. Please advise me on my issue.
Thank you
Yes, you definitely should store the [BookingMonth] as numeric. Maintaining a "month" column as text will be a nuisance in the long run, since "August"<"January" and "12"<"2". You'd have to do at least a certain amount of juggling to convert the text values to numeric values, so make like easy for yourself and just maintain them as numeric. (Note that you can always format them as text if you want to use them in reports.)
As for your search requirements, if the user supplies a [chosenBookingYear], [chosenBookingMonth], and [numberOfMonthsToBook] then you can use the VBA DateAdd function to derive [endOfBookingYear] and [endOfBookingMonth] safely, accounting for "next year" values...
endOfBookingYear = Year(DateAdd("m", numberOfMonthsToBook - 1, DateSerial(chosenBookingYear, chosenBookingMonth, 1)))
...and...
endOfBookingMonth = Month(DateAdd("m", numberOfMonthsToBook - 1, DateSerial(chosenBookingYear, chosenBookingMonth, 1)))
Finally, to perform the lookup without looping through individual rows you can concatenate [BookingYear] and [BookingMonth] together to create something like "2013/05" using...
BookingYear & "/" & Format(BookingMonth, "00")
...so then you can create a SELECT query something like this:
SELECT * FROM Payment
WHERE HouseID = chosenHouseID AND
(
(BookingYear & "/" & Format(BookingMonth, "00"))
BETWEEN (chosenBookingYear & "/" & Format(chosenBookingMonth, "00"))
AND (endOfBookingYear & "/" & Format(endOfBookingMonth, "00"))
)