Multiple value in a column sql - sql

I'm working on an SSIS package. This package loads information from a form a verdure files. the package works perfectly, however my issue is in one of the column called 'SpecialUnit'.
On the form the customer can select 23 values and all this values get recorded as a comma separated. In my SSIS I have created different fields for all 23 values I wanted all this values to show 1 when the person selects them.
Example.
CASE WHEN sp.CodeText = 'Transit Dept.'
THEN 1
ELSE 0
END AS FollowUpByTransit,
I have a table that separates the comma delimiter, but when loading I do not have a value I want which is 1 or 0.

Can you make your 23 fields as calculated fields, then on the equation for each field you can use something like the below
As case when CodeText like '%Transit Dept%' then 1 else 0 end as FollowUpByTransit
So you would need to use the like operator, so you ignore the commas and other values.
If your code words may be a bit similar to each other, you can go with the idea HABO presented and thats somthing like the below
As case when (','+CodeText+',') like '%,Transit Dept,%' then 1 else 0 end as FollowUpByTransit
Hope this helps.

Related

PostgreSQL - Assign integer value to string in case statement

I need to select one and only 1 row of data based on an ID in the data I have. I thought I had solved this (For details, see my original question and my solution, here: PostgreSQL - Select only 1 row for each ID)
However, I now still get multiple values in some cases. If there is only "N/A" and 1 other value, then no problem.. but if I have multiple values like: "N/A", "value1" and "value2" for example, then my case statement is not sufficient and I get both "value1" and "value2" returned to me. This is the case statement in question:
CASE
WHEN "PQ"."Value" = 'N/A' THEN 1
ELSE 0
END
I need to give a unique integer value to each string value and then the problem will be solved. The question is: how do I do this? My first thought is to somehow convert the character values to ASCII and sum them up.. but I am not sure how to do that and also worried about performance. Is there a way to very simply assign a value to each string so that I can choose 1 value only? I don't care which one actually... just that it's only 1.
EDIT
I am now trying to create a function to add up the ASCII values of each character so I can essentially change my case statement to something like this:
CASE
WHEN "PQ"."Value" = 'N/A' THEN 9999999
ELSE SumASCII("PQ"."Value")
END
Having a small problem with it though.. I have added it as a separate question, here: PostgreSQL - ERROR: query has no destination for result data
EDIT 2
Thanks to #Bohemian, I now have a working solution, which is as follows:
CASE
WHEN "PQ"."Value" = 'N/A' THEN -1
ELSE ('x'||LPAD(MD5("PQ"."Value"),16,'0'))::bit(64)::bigint
END DESC
This will produce a "unique" number for each value:
('x'||substr(md5("PQ"."Value"),1,8))::bit(64)::bigint
Strictly speaking, there is a chance of a collision, but it's very remote.
If the result is "too big", you could try modulus:
<above-calculation> % 10000
Although collisions would then be a 0.01% chance, you should try this formula against all known values to ensure there are no collisions.
If you don't care which value gets picked, change RANK() to ROW_NUMBER(). If you do care, do it anyway, but also add another term after the CASE statement in ORDER BY, separated by a comma, with the logic you want - for example if you want the first value alphabetically, do this:
...
ORDER BY CASE...END, "PQ"."Value")
...

Netsuite sql case statement where both are true

I am trying to create a formula for the following criteria.
WHEN usernotes.notetitle CONTAINS ‘collection’ AND usernotes.notedate is within the last thirty days
Here is what I have right now. It lets me write a case then set the value.
CASE WHEN ({usernotes.notetitle} CONTAINS 'collection') AND (TRUNC({today}-{usernotes.notedate}) BETWEEN 0 AND 30) THEN 1 ELSE 0 END
I don’t know if CONTAINS is the right syntax and I’m not sure if I can combine the two formulas or if I did it right.
I believe you are combining your conditions correctly with AND.
To do string comparisons, use LIKE and the % wildcard:
CASE WHEN ({usernotes.notetitle} LIKE '%collection%') AND (TRUNC({today}-{usernotes.notedate}) BETWEEN 0 AND 30) THEN 1 ELSE 0 END
If you only need to look for notes that start with collection, then just remove the first %.
See the NetSuite Help article titled SQL Expressions for details on all the SQL functions you can use.
See this page on LIKE for more details about pattern matching.

How to cut the last 3 values off a field in an SQL where clause?

I'm trying to compare a value from a field but only using the last 3 values.
WHERE table1.FieldValue(-3) NOT LIKE table2.Fieldvalue
obviously (-3) doesn't work. I've tried converting it to a string then trying to play with it that way. But to no success.
Any suggestions welcome.
Thanks
EDIT:
I'm looking at postcodes.
So table1.Fieldvalue = N90HXF
and table2.Fieldvalue = N90
I want to trim the HXF off so I can compare the two.
You can use the LEFT() function to compare only the first characters of a string, exluding the last 3 from the value.
WHERE LEFT(table1.FieldValue, LEN(table1.FieldValue)-3) NOT LIKE table2.FieldValue
As I would see things from your request, you can exclude the values which are less than 3 characters from the results, so you would just add another condition in your WHERE clause, like:
WHERE LEN(table1.FieldValue) > 3
AND LEFT(table1.FieldValue, LEN(table1.FieldValue)-3) NOT LIKE table2.FieldValue
But if you do not want to exclude those values from your result, but you would rather that they are added at the end of your query, you can use a condition like:
WHERE LEFT(table1.FieldValue, CASE
WHEN LEN(table1.FieldValue) < 3
THEN table1.FieldValue + REPLICATE('', 3)
ELSE LEN(table1.FieldValue) - 3
END) NOT LIKE table2.FieldValue
ORDER BY LEN(table1.FieldValue) DESC
The above condition will pad (add) 3 whitespaces to all of your values, so that the LEFT() function will not result in an error even if the value has less than 3 characters.

Alternative to like/ like any?... regexp?

I have a TERADATA dataset that resembles the below:
Customer_ID | Targeting_Region
12 | targ=EU, targ=!Eu.Fr
34 | targ=Asia
56 | targ=!EU
The '!' denotes 'does not equal'. For example, the customer in Row #1 wants to target the EU, but exclude France.
I want to create a field that flags (with a '1') any row where there is 'positive' targeting. By 'positive' targeting I am referring to any row where a specific region as been explicitly INCLUDED ('negative' targeting would be where a region is explicity EXCLUDED, such as the exclusion of France in Row #1). For example, Row #1 contains both positive and negative targeting, Row #2 contains only positive targeting, Row #3 contains only negative targeting.
The problem I am encountering is that a simple case statement won't work (as far as I can tell). I have tried the 2 statements below:
(case when targeting_region like '%targ=%'; then 1 else 0 end) as target_flag
(case when ((targeting_region like '%targ=%';) and (targeting_region not like '%targ=!%';)) then 1 else 0 end) as target_flag
The 1st statement above doesn't work because it will return 1 for both 'targ=' and 'targ=!
The 2nd statement above doesn't work because it will return 1 for rows that ONLY have positive targeting. As such, Row #1 (above) would return a 0 (I want it to return a 1)
Note that that value following 'targ=' could also be a number. E.g., 'targ=12345'
Any ideas on how I could accomplish this? I have heard that teradata has something called regexp but I have been unable to find a good explanation of it after quite a bit of searching.
Thanks!
Maybe not exactly what you're looking for, but if you want a 1 only when there is a positive target and no negative target, then why not make it 0 if there exists a negative target and 1 otherwise?
For example,
case when targeting_region like '%targ=!%' then 0
when targeting_region like '%targ=%' then 1
else null -- Optional if you want to handle when no targeting regions exist
end as target_flag
Would something like this work?
(case when REGEXP_INSTR(targeting_region,'targ=[A-Z,a-z]') = 0; then 0 else 1)
I found syntax and example of REGEXP_INSTR() at
http://www.info.teradata.com/HTMLPubs/DB_TTU_14_00/index.html#page/SQL_Reference/B035_1145_111A/Regular_Expr_Functions.085.03.html#ww14955402
Because there was too little info at this site, you will have to fiddle with it to get it to work.
For example...
The equal sign in "...targ=...", and maybe even the left and right brackets, may need to be escaped, perhaps with backslash. Also, the above assumes that if there is no match, the function returns 0 (rather than NULL). It may need to be changed from "=0" to "IS NULL". Also, I assume that the parameters after the first two are optional. You may need to specify them, e.g., "1,1,i". Also, the expression could be simplified a bit, for example by using a shortcut for [A-Z,a-z], if you can find better documentation.
Explanation:
The second parameter specifies a "pattern" to look for in the first parameter.
1. "targ=" looks for exactly those characters.
2. "[A-Z,a-z]" looks for an alphabetic character. If a "!" occurs, it will not match and the search will proceed with the rest of the string.
3. REGEXP_SUBSTR() returns the character position where the pattern was found in the string. That's overkill because you only want to know yes it was found or no it was not, but hopefully it works because I couldn't find a simpler function.
If I understood you correctly you want 1 if there's any included target regardless of additional excluded regions?
This searches for 'targ=' followed by any other character than '!':
CASE WHEN REGEXP_INSTR(Targeting_Region,'targ=[^!]') = 0 THEN 0 ELSE 1 END
If your release doesn't include REGEXP function there might be OREPLACE:
CASE WHEN POSITION('targ=' IN OREPLACE (Targeting_Region, 'targ=!', '')) > 0 THEN 1 ELSE 0 END

SQL - Conditionally joining two columns in same table into one

I am working with a table that contains two versions of stored information. To simplify it, one column contains the old description of a file run while another column contains the updated standard for displaying ran files. It gets more complicated in that the older column can have multiple standards within itself. The table:
Old Column New Column
Desc: LGX/101/rpt null
null Home
Print: LGX/234/rpt null
null Print
null Page
I need to combine the two columns into one, but I also need to delete the "Print: " and "Desc: " string from the beginning of the old column values. Any suggestions? Let me know if/when I'm forgetting something you need to know!
(I am writing in Cache SQL, but I'd just like a general approach to my problem, I can figure out the specifics past that.)
EDIT: the condition is that if substr(oldcol,1,5) = 'desc: ' then substr(oldcol,6)
else if substr(oldcol,1,6) = 'print: ' then substr(oldcol,7) etc. So as to take out the "desc: " and the "print: " to sanitize the data somewhat.
EDIT2: I want to make the table look like this:
Col
LGX/101/rpt
Home
LGX/234/rpt
Print
Page
It's difficult to understand what you are looking for exactly. Does the above represent before/after, or both columns that need combining/merging.
My guess is that COALESCE might be able to help you. It takes a bunch of parameters and returns the first non NULL.
It looks like you're wanting to grab values from new if old is NULL and old if new is null. To do that you can use a case statement in your SQL. I know CASE statements are supported by MySQL, I'm not sure if they'll help you here.
SELECT (CASE WHEN old_col IS NULL THEN new_col ELSE old_col END) as val FROM table_name
This will grab new_col if old_col is NULL, otherwise it will grab old_col.
You can remove the Print: and Desc: by using a combination of CharIndex and Substring functions. Here it goes
SELECT CASE WHEN CHARINDEX(':',COALESCE(OldCol,NewCol)) > 0 THEN
SUBSTRING(COALESCE(OldCol,NewCol),CHARINDEX(':',COALESCE(OldCol,NewCol))+1,8000)
ELSE
COALESCE(OldCol,NewCol)
END AS Newcolvalue
FROM [SchemaName].[TableName]
The Charindex gives the position of the character/string you are searching for.
So you get the position of ":" in the computed column(Coalesce part) and pass that value to the substring function. Then add +1 to the position which indicates the substring function to get the part after the ":". Now you have a string without "Desc:" and "Print:".
Hope this helps.