SQL involving columns with comma delimited strings and comparison - sql

I am updating the requirement..Basically A string can have 2 or 3 or 4 decimal places decimal places instead of the two decimal places as show below.
Suppose I have a record with a comma delimited strings in a column name "Version"
Say we have a record (A) containing having these values in its "Version" column
Version=10.1.2.4, 10.4.3.4,11.6.0, (the column has comma delimited strings)
I am passing an sql parameter called #VersionCheck
IF #VersionCheck = 11.6.0 and Version does not have any value like 11.5.6 (Note the 11 matches with the 11 in 11.6.0)
I want to return the record
So here are some examples all comparing with the parameter #VersionCheck= 11.6.0
Version=10.1.2,10.4.3.45 return this record
Version=10.1.2,10.4.3,10.4.4.5,11.6.0 return this record (if we have a match 11.6.0 and there are no strings starting with 11.something that is not equal to 11.6.0(parameter passed) we return this record)
Version= 10.1.2,10.4.3,11.6.0.2 do not return this record (to check, take the string before the first decimal point, in this case is 11, however 11.6.0.2 and 11.6.0 is not the same so it should not match)
How do I write the sql query to have this logic in the where clause?
If the parameter passed is #VersionCheck = 10.6.8 I do not want it to match if the strings in the comma delimited column has say 10.5.4 Basically take the characters before the first decimal and if they are equal (10=10), the rest of its values have to be the same else it should not match.
This is my solution below in sql server 2008 syntax
Note that #SU_Version is my parameter
and SuVersion.fieldValue is the column which has the comma delited string values like 10.1.2,10.3.4 etc
WHERE (CASE WHEN '%#SU_Version%' <> '' AND suVersion.fieldValue LIKE LTRIM('#SU_Version')
THEN suVersion.fieldValue
ELSE '%'
END like CASE WHEN '%#SU_Version%' <> ''
THEN '%#SU_Version%'
ELSE '%'
END
AND
(CASE WHEN LTRIM('#SU_Version') <> '' AND suVersion.fieldValue LIKE SUBSTRING(LTRIM('#SU_Version'),1, CHARINDEX( '.',LTRIM('#SU_Version'))-1)
THEN suVersion.fieldValue
ELSE'%'
END not like CASE WHEN LTRIM('#SU_Version')<> ''
THEN SUBSTRING(LTRIM('#SU_Version'),1, CHARINDEX( '.',LTRIM('#SU_Version'))-1) + '%'
ELSE '%'
END
AND
CASE WHEN LTRIM('#SU_Version') <> '' AND suVersion.fieldValue LIKE SUBSTRING(LTRIM('#SU_Version'),1, CHARINDEX( '.',LTRIM('#SU_Version'))-1)
THEN suVersion.fieldValue
ELSE'%'
END not like CASE WHEN LTRIM('#SU_Version')<> ''
THEN SUBSTRING(LTRIM('#SU_Version'),1, CHARINDEX( '.',LTRIM('#SU_Version'))-1) + '%'
ELSE '%'
END)
)

Since your design basically thwarts any attempts to use an index on the Version column anyway, this will give you rows where there is an exact match
...
WHERE ',' + Version + ',' LIKE '%,' + #VersionCheck + ',%'
For the funky requirements you have, try this (this assumes all version strings will contain exactly two decimal places):
DECLARE #v TABLE(Version VARCHAR(MAX));
INSERT #v SELECT ('10.1.2,10.4.3')
UNION ALL SELECT ('10.1.2,10.4.3,11.6.0')
UNION ALL SELECT ('10.1.2,10.4.3,11.5.2');
DECLARE #SU_Version VARCHAR(32);
SET #SU_Version = '11.6.0';
DECLARE
#p1 VARCHAR(10),
#p2 VARCHAR(10);
SELECT
#p1 = PARSENAME(#SU_Version, 3),
#p2 = PARSENAME(#SU_Version, 2);
SELECT Version = SUBSTRING(Version, 2, LEN(Version)-2) FROM
(
SELECT Version = ',' + Version + ',' FROM #v
) AS v WHERE
(
Version LIKE '%,' + #SU_Version + ',%'
OR
Version NOT LIKE '%,' + #p1 + '.%,%'
AND NOT
(
Version LIKE '%,' + #p1 + '.%,%'
AND
Version NOT LIKE '%,' + #p1 + '.' + #p2 + '.%,%'
)
);

Related

sql concatenation with blank cells

So I am extracting data from one table to another
SELECT *
LTRIM(ADRESSE + ',' + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]
Issue is that if the cells are blank i still get a comma ,
I have tried using & instead of + but nvarchar is incompatible in the '&' operator. Any ideas how I only insert the comma if there is something to concatenate?
You want the equivalent of CONCAT_WS() in other databases. You can do this with STUFF() and some string logic in SQL Server:
SELECT c.*
STUFF( (COALESCE(',' + ADRESSE, '') +
COALESCE(',' + ADRESSE2, '') +
), 1, 1, ''
) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT] c;
This structure is convenient, because you can just add more COALESCE() expressions for more columns.
use case expression
SELECT *, LTRIM(ADRESSE + case when ADRESSE is not null then ',' end + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]
use case when for null checking
SELECT *
LTRIM(ADRESSE + case when ADRESSE2 is not null then
',' else '' end + ADRESSE2) AS ADDRESS12
FROM [Homestore].[dbo].[CLIENT]

WHERE clause based on part of a VARCHAR column

I have a query where I need to search the numerical part of a string in SQL Server.
In the number column above needs to be searchable as a variable in the query.
Wildcards does not work:
SELECT PK_Story
FROM Story
WHERE ProductId = #productParam
AND Number LIKE '%' + #numberParam + '%';
because this would also return 132 and 232 for example.
So how can I search for a specific number after the '-'. As you can see I can't do charindex because of the variable prefix length.
What about LIKE '%-' + #numberParam?
You can use substring and charindex combination to get the result.
SELECT PK_Story
FROM Story
WHERE ProductId = #productParam
AND #numberParam like
'%' + case when charindex('-', Number) > 0
then substring(Number, charindex('-', Number) +1, len(Number)) + '%'
else Number
end + '%'
what about this
declare #My_Number as varchar(50)='8'
SELECT PK_Story
FROM Story
WHERE ProductId = #productParam
AND substring(Number, charindex('-', Number) +1, len(Number)) like
#My_Number +'%'
Or, if want equal
SELECT PK_Story
FROM Story
WHERE ProductId = #productParam
AND substring(Number, charindex('-', Number) +1, len(Number)) =
#My_Numbe

SQL search issue

I know this is a simple question but here it goes. I've created a search button in Visual Studio using an SQL Statement. It works for first name and last name, but I also want it to search int such employee Id's. Here is the code :
SELECT ID, fName, lName, Discription, Box
FROM tb1
WHERE (fName LIKE '%' + #fName + '%') OR (lName LIKE '%' + #lName + '%') OR (ID LIKE '%' + #ID + '%')
When I test it, I get the error :
"Conversion failed when converting the varchar value '%' to data type int.
ID LIKE '%' + #ID + '%'
ID is an integer, '%' + #ID + '%' is a string. It can't really compare. An integer either is a value or it isn't. The % wildcards wouldn't mean anything to an integer.
I'm assuming what you want to do is convert the integer into a string so that you can match substrings of it. So, for example, searching for "1" would match on any integer which contains a "1" (10, 11, 12, 451, etc.). To do that you should simply need to convert the integer value to a string value in the WHERE clause:
(CAST(ID AS varchar(10)) LIKE '%' + #ID + '%'
(This assumes that your integer will never be more than 10 characters long. Adjust that value as necessary.)
You cannot use LIKE with integers, so you will have to convert the ID to varchar.
To convert you can use CAST or CONVERT:
http://msdn.microsoft.com/en-us/library/ms187928.aspx
Ex:
CAST(ID as varchar)
Your query:
SELECT ID, fName, lName, Discription, Box
FROM tb1
WHERE (fName LIKE '%' + #fName + '%') OR (lName LIKE '%' + #lName + '%') OR (CAST(ID as varchar) LIKE '%' + #ID + '%')
The LIKE syntax is compatible only with character-associated data types. INT types do not fall under this category.
Reference: http://msdn.microsoft.com/en-us/library/ms179859.aspx

What is happening in this T-SQL code? (Concatenting the results of a SELECT statement)

I'm just starting to learn T-SQL and could use some help in understanding what's going on in a particular block of code. I modified some code in an answer I received in a previous question, and here is the code in question:
DECLARE #column_list AS varchar(max)
SELECT #column_list = COALESCE(#column_list, ',') +
'SUM(Case When Sku2=' + CONVERT(varchar, Sku2) +
' Then Quantity Else 0 End) As [' +
CONVERT(varchar, Sku2) + ' - ' +
Convert(varchar,Description) +'],'
FROM OrderDetailDeliveryReview
Inner Join InvMast on SKU2 = SKU and LocationTypeID=4
GROUP BY Sku2 , Description
ORDER BY Sku2
Set #column_list = Left(#column_list,Len(#column_list)-1)
Select #column_list
----------------------------------------
1 row is returned:
,SUM(Case When Sku2=157 Then Quantity Else 0 End) As [157 -..., SUM(Case ...
The T-SQL code does exactly what I want, which is to make a single result based on the results of a query, which will then be used in another query.
However, I can't figure out how the SELECT #column_list =... statement is putting multiple values into a single string of characters by being inside a SELECT statement. Without the assignment to #column_list, the SELECT statement would simply return multiple rows. How is it that by having the variable within the SELECT statement that the results get "flattened" down into one value? How should I read this T-SQL to properly understand what's going on?
In SQL Server:
SELECT #var = #var + col
FROM TABLE
actually concatenates the values. It's a quirks mode (and I am unable at this time to find a reference to the documentation of feature - which has been used for years in the SQL Server community). If #var is NULL at the start (i.e. an uninitialized value), then you need a COALESCE or ISNULL (and you'll often use a separator):
SELECT #var = ISNULL(#var, '') + col + '|'
FROM TABLE
or this to make a comma-separated list, and then remove only the leading comma:
SELECT #var = ISNULL(#var, '') + ',' + col
FROM TABLE
SET #var = STUFF(#var, 1, 1, '')
or (courtesy of KM, relying on NULL + ',' yielding NULL to eliminate the need for STUFF for the first item in the list):
SELECT #var = ISNULL(#var + ',', '') + col
FROM TABLE
or this to make a list with a leading, separated and trailing comma:
SELECT #var = ISNULL(#var, ',') + col + ','
FROM TABLE
You will want to look into the COALESCE function. A good article describing what is happening can be seen here.

What is the best way to collapse the rows of a SELECT into a string?

In a SQL statement ( or procedure ) I want to collapse the rows of this table into a single comma delimited string.
simpleTable
id value
-- -----
1 "a"
2 "b"
3 "c"
Collapse to:
"a, b, c"
You can concatenate using an embedded 'set' statement in a query:
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + isnull(value,'')
from simpleTable
print #combined
(Note that the first isnull() initialises the string, and the second isnull() is especially important if there's any chance of nulls in the 'value' column, because otherwise a single null could wipe out the whole concatenation)
(edited code and explanation after comments)
Edit (ten years later):
SQL Server 2017 introduced the STRING_AGG() function which provides an official way of concatenating strings from different rows. Like other aggregation functions such as COUNT(), it can be used with GROUP BY.
So for the example above you could do:
select string_agg(value, ', ')
from simpleTable
If you had some other column and you wanted to concatenate for values of that column, you would add a 'group by' clause, e.g:
select someCategory, string_agg(value, ', ') as concatValues
from simpleTable
group by someCategory
Note string_agg will only work with SQL 2017 and above.
This will only work in MSSQL 2005+
select value + ',' from simpletable for xml path ('')
..one way to prevent the extra comma:
select case(row_number() over (order by id))
when 1 then value else ',' + value end
from simpletable
for xml path ('')
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
Results:
1, 2, 4
This is based on #codeulike answer, but will prevent losing the portion of the string that gets concatenated before a null "value" is concatenated on.
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + ISNULL(value,'')
from simpleTable
print #combined