MySQL conditional variable inside text field - mysql

This might seem like a strange one, but can you store a conditional variable inside a text field (or something that can be made to work like one)?
I'm creating a notification system that groups notification by date and type, so if 2 or more of the same type are created in the same day it will group the notifications together and provide a count (e.g. Person1 and 3 others have done something).
The notification messages are stored in a table as a template e.g.
[[value]] has just done something
[[value]] is then replaced with Person1's name (and count OTHERS) by using
REPLACE(t1.message,
'[[value]]',
IF(t1.value_as_user=1,
CONCAT(t1.forename, ' ', t1.surname, IF((count((t1.id + DATE(t1.date)))-1)<>0,
CONCAT(' and ', (count((t1.id + DATE(t1.date)))-1), ' other'),
'')),
t1.value)) as 'message'
The only problem with this is it would mean that grammatically the message would no longer make sense i.e. "Person1 and 2 others has just done something" should now be "Person1 and 2 others have just done something"
Is there a way to select a string within a text field (like I have done with [[value]]) except have it where it would be something like [[has/have]] and depending on the count the correct one could chosen?

Sometimes you can change the sentence to avoid the grammatical variability:
Something has been done by Person1 and 2 others
(If you read The Elements of Style by Strunk & White, you may be conditioned to recoil at the passive voice. The above trick may seem like cheating. But don't let them bully you.)
Otherwise, no, there's no function in MySQL that can analyze a string and find out its grammatical usage in English and automatically conjugate verbs.
You could make [[has/have]] be another meta-field in your string, and then replace it with another expression based on the count.
But frankly, I wouldn't do the string formatting in an SQL expression. Not only for this reason, but because string-manipulation in SQL is clumsy compared to literally any other language (except Java of course).

Related

SSIS Substring Error Using Case When with Right Function

I am using Below code in my derived column of SSIS to remove title in Name column such as Mr,Mrs,Ms and Dr.
Ex:-
Mr ABC
MS XYZX
Mrs qwrer
DR ADCS
SO I am removing the title of the name.
SUBSTRING( [Name] , 1, 3)=="Mr" && LEN( [Name] ) >2 ? RIGHT([Name],LEN([Name])-2)
But getting Error as incomplete token or invalid statement.
Please help.
any other suggestion to remove the prefixes are also welcome but need to Use transformation.
A different way to think about the problem is that you want to look at the first "word" in the column Name where "word" is the collection of characters from the start of the string to the first space.
String matching in SSIS is case-sensitive so you'll want to force the first word to lower/upper case - however your master list of titles is cased (and then ensure the title list is all lower/upper case).
I am an advocate of making life easier on yourself so I'll add a Derived Column, actually lots of derived columns, that will identify the position of the first space in Name and I'll call this FirstSpace
DER GetFirstSpace
Add a new column, called FirstSpace. The expression we want to use is FINDSTRING
FINDSTRING([Name], " ", 1)
That will return the position of the first instance of a space (or zero if no space was found).
DER GetFirstWord
Add another derived column after the DER GetGetFirstSpace. We need to do this so we can inspect the values we're passing to get the first word. Do it all in a single Derived column and when you get something wrong, you won't be able to debug it and the real cost of development is maintenance. New column, FirstWord will be type DT_WSTR 4000 because that's what happens when you use the string manipulation expressions. I am going to force this to upper case as I'll need it later on.
UPPER(SUBSTRING([Name], 1, [FirstSpace]))
TODO: Verify whether that will be "DR" or "DR " with trailing space as I'm currently coding this by memory.
TODO: What happens if FirstSpace is 0 - we might need to make use of ternary operator ?:
At this point in the data flow, we have a single word in a column named FirstWord what we need to do is compare that to our list of known titles and if it exists, strip it from the original. And that's an interesting problem.
DER GetIsTitleMatched
Add yet another Derived column, this time to solve whether we've matched our list of titles. This will be a boolean type column named IsTitleMatched
[FirstWord] == "DR" || [FirstWord] == "MRS" || [FirstWord] == "MR" || [FirstWord] == "MS"
Following that pattern "FirstWord is exactly equal literal text OR..." when this derived column evaluates, we'll know whether the first word is something to be removed (finally)
DER SetFinalName
Here we're going to add yet another column, NameFinal The magic of stripping out the bad word will be that we use the RIGHT expression starting at the position of that opening space and going to the end of the word. You might need to add a left TRIM in there based on whether the RIGHT operation is inclusive of the starting point or not. Again, free handing at the moment so good but no guarantee of perfection.
(IsTitleMatched) ? RIGHT([Name], [FirstSpace]) : [Name]
I do violate my own rule here as I have a quasi complex expression there in the positive case. Feel free to insert a derived column task that computes the stripped version of the name.
At this point, you've got 4 to 5 derived columns in your data flow but you can add a data viewer between each to ensure you're getting the expected result. You're welcome to solve this in your own manner but that's the easiest approach I can think of.

Using backspace - CHR(8) - in Access Query

I have a parts management MS Access database. One of the fields is rarely used - it stores whether a part in inventory is actually rare variant of a more common part. Normally the field is used as a suffix to the primary part number and the database generates that in reports while storing the parent part in the database. (One primary database which controls part numbers does not contain any information on the variants, but it's important to store because the storefront database does.)
I've found in some cases the variant is not simply a suffix. In some cases the correct variant part number eliminates a character from the parent part. For example part "3069b" has a variant "3069bpb198". But I found part "30361c" has a variant "30361pb016" which eliminated the "c".
My preferred solution is to encode a backspace character into the field for those variants which require it. Then when i concatenate the parent part number with the variant number, "30361c" & "\bpb016" becomes "30361pb016". However the output I get in my Access query is "30361c□pb016".
The concatenation formulas in the query I've tried are:
PartNum: [pl].[PartID] & [variant] 'returns "30361c\bpb016"
PartNum: Replace([pl].[PartID] & [variant],"\b",Chr(8))
Is what I'm trying to do possible? And if so what am I doing wrong?
I'd really like to avoid having to change the database so the variant contains the full part number instead of a suffix.
How about:
PartNum: left([pl].[PartID],len([pl].[PartID])-1) & [variant]
Well, you might be able to concatenate the backspace, but how and if that will effect the display of the data is a MASSIVE different issue. The use of ctrl-H goes back to the days of green screens, and even the tele-type age. In other words you want a way to optional remove a character, and using ctrl-H with modern GUI and systems that really don't represent a ASCII character steams means that the question is not about how to make ctrl-H work to chop a char, but how can one chop off a character based on some kind of information.
In other words ctr-H is a crazy approach unless you using a ASCII green screen, or say a printer.
I also would not introduce a non printable character into that data, since you can't type that information into a field, and worse yet you thus can't search, sort and deal with that column as data.
It gets even worse. Your business rule is that "some" data in one column is to effect the display of another column!!!! This breaks the relational data model so bad, it is not even funny.
What you need is to add a bit column (true/false). In fact, really what needs to occur is the selection of the first column needs to take into account the 2nd column, and a DIFFERNT choice should have been made here.
Now this trick/idea might have worked 25 years ago when most computers were ASCII, working with green screens, and output to a screen/terminal or even for crazy sakes a teletype machine? Well, then ctrl-H would work.
Modern systems are displaying data in a graphical format, and the data is not really ASCII anymore - but is saved in uni-code. (which allows display in just about any language or region).
Now, assuming that the people who suffered some serious brain damage to consider polluting the data this way?
Well, you could use this function:
Public Function vScrub(ByVal s As Variant) As String
Dim c As Integer
If IsNull(s) Then
vScrub = ""
Exit Function
Else
c = InStr(s, Chr(8))
Do While c <> 0
s = Left(s, c - 2) & Mid(s, c + 1)
c = InStr(s, Chr(8))
Loop
End If
vScrub = s
End Function
So, place the above in a standard code module (not a class module, nor a forms module).
Once done, then any form, any report, and yes even any query can simply wrap the string expression with above
eg:
vScrub([Col1] & [col2])
Edit:
Modify routine to work for multiple chr(8) in the string.

How can I group data by matching identical cells in same column then counting instances of a related column?

data output
I am pretty new to Webi and am having an issue creating a variable. I'm trying to check if there is more than 1 email address for each entity legacy account number and if 1 of the contact names contains "Annual Report". So when I flag each entity legacy account number for no email only the ones without a contact name that contains "Annual Report" will be pulled. In the example above only the yellow groups should be called no email. Right now all of them are being pulled into no email. I have tried using if and match as those are what I am most familiar with. Does anyone have any suggestions?
There are number of ways you could do this. I am going to give an example using two variables, but you could easily combine them into one.
Has No Email Var=If(Match(Upper([Contact EmailAddress]); "NOEMAIL*"); 1; 0)
Annual Report Contact Name Var=If(Match(Upper([Contact Name]); "ANNUAL REPORT*"); 1; 0)
Then you would apply a report filter with two components...
Has No Email Var = 1
AND
Annual Report Contact Name Var = 0
Let me explain a few things...
The purpose of the Upper function is the Match function is case sensitive. If you know your email address are always lower case then you could remove that the Upper function and have it match on "noemail*".
It is significant that I only have a asterisk ("*") at the end of the string being sought. That will only find a match where the corresponding column value starts with that string. If you want it to be true whenever the string is found anywhere in the column being searched you would be asterisks on both ends.
You could also put limiting criteria in your query filter. But here is where thing can get confusing. Within the query filter you can choose the Matches pattern operator. However, the wildcard character is different ("%" rather than "*") and you do not put double-quotes around your search text. So you would have some thing like this...
Contact EmailAddress Matches pattern noemail%
AND
Contact Name Different from pattern Annual Report%
I am sure you noticed I didn't convert the search text to uppercase. In the Query Panel Web Intelligence is case-insensitive and would likely follow the case-sensitivity of the database of the source data. All of our databases are case-insensitive so if yours is case-sensitive you may need to play around this this a bit. Or just go with the approach of creating the variables and report filters as I initially laid out.
If you want a wildcard for a single character rather than multiple characters (which is what "*" and "%" will do) you need to use a "?" within your variable definition or a "_" in your query filter.
Hope this helps,
Noel

Reporting services: Join all field on a dataset

In a report, I've a dataset with a filter(based on a MultiValue parameter).
This dataset contains two field: Id and Name.
I need to display somewhere the concatenation of all names:
Name1 / Name2 / Name3
The problem is that the join method works only on array, and then I cannot specify a dataset as value.
I looked in custom code too, but I didn't found anything working.
How should I do this ?
I may be a bit late for this but for anyone that's interested in this, there is a rather easy way of doing this in SSRS:
=Join(LookupSet(1,1,Fields!Name.Value, "DatasetName")," / ")
SSRS-2008 R2 and higher...
1. Using LookupSet
If you're beyond the 2008 version OP has, there exists a good solution:
=Join(LookupSet(1, 1, Fields!Name.Value, "DatasetName"), " / ")
Credit for this answer using the LookupSet solution goes entirely to #urbanhusky's answer.
SSRS-2008 and lower...
I'm keeping this answer though because it aggregates #urbanhusky's solution with the solutions available to poor souls stuck with OP's version of SSRS and below.
In SSRS 2008 there's only three "options" as far as I can see, each with its own downside. The first one's probably the least hackish.
2. Extra parameter
Create an internal parameter (e.g. "NameParameter", see this SO answer or MSDN) with Allow Multiple Values. Set the default value of the parameter to the Name field from your dataset. Then use the function =Join(Parameters!NameParameter.Value, " / ") to show the joined names in a textbox.
This may be your best bet, but if there are a lot of values the parameter may not work very well.
3. Use a List
Create a List and drag/drop the Name field to it. If necessary, group on the Name as well.
The disadvantage here is that (AFAIK) the list can't be made to show horizontally.
4. Use a Matrix
Oh boy, this one's real ugly. Nonetheless, here goes: create a matrix, drag the Name field to the column header, and hide the first column as well as the second row (for displaying the data).
The main disadvantage is that it's a hack (and quite some overkill), plus you'll have to trim the last seperator character manually with an expression.

Searching Mysql for similar string

People have different ideas of how to search for the same term.
For example Tri-Valley, Trivalley, Tri Valley (and possibly even incorrect spellings)
Currently that search is done like this
SELECT * FROM `table` WHERE `SchoolDistrict` LIKE '%tri valley%';
Is there an easy way to say 'space dash or no space' without writing out three like statements?
It seems like it could easily be done:
SELECT * FROM `table` WHERE `SchoolDistrict` LIKE '%tri%valley%';
But this only works if the initial input is 'tri-valley' or 'tri valley' If the initial input is 'trivalley' I have no idea where to place the % (theoretically that is, actually, I do, as we are only looking at about a dozen different school districts, but I'm looking to solve the larger problem)
You could consider using SOUNDEX, or SOUNDS LIKE if you have a lot of incorrect spellings. If you've got a lot of rows (or even if you don't), it might be wise to store the output of the SOUNDEX in an additional column.
I'd also recommend -- in the interests of accuracy -- introducing a separate table with an authoritative list of school districts, and run a query to find those which aren't in that list.
MySQL has a function called Sounds like.
link text
An alternative here is to recast the problem from search to select, if possible. Instead of letting your users enter free-form text to choose a school district, if you have a set of school districts generate a dropdown (or set of cascading dropdowns if the list is large, say by county, then by school district) and allow the user to select the appropriate one. Use this both for "searching" and for data entry to eliminate non-canonical entries. Obviously this only works when you can enumerate all of the entries.
Alternatively you could allow the user to choose a starts with or contains type search and simply generate the appropriate SQL ('tri%' or '%tri%') based on the selected search type. If the user understands that the search type is starts with or contains, they will likely adjust their search string until it yields the results they need.
The second statement you posted should do the trick:
SELECT * FROM 'table' WHERE 'SchoolDistrict' LIKE '%tri%valley%';
What you should do before you pass the search term into the select statement is to replace all characters and spaces with the % sign. For example,
SearchTerm = SearchTerm.Replace(" ","%");