Highlighting rows with trailing and leading space/s - sql

I want to highlight rows with trailing and leading spaces. I've below query but want to know if there is better more efficient way to achieve this.
SELECT *
FROM DummyTable lc
WHERE
(lc.Code LIKE '% ' OR lc.Code LIKE ' %' or lc.Code like '% % %' OR lc.Code like '% % %')
AND (lc.StartDate <= getdate() AND lc.EndDate > getdate())
AND (lc.CodeTypeID <> 27)
ORDER BY 4 DESC
Please note that I don't want to remove space from the field "Code" but just highlight in my result set.

There is not a more efficient method, but you can reduce the number of comparisons:
WHERE CONCAT(' ', lc.Code, ' ') LIKE '% %' AND
lc.StartDate <= getdate() AND
lc.EndDate > getdate() AND
lc.CodeTypeID <> 27
This adds a space to the beginning and end and then looks for two spaces in a row (which seems to be your intention despite how the question is phrased).
Unfortunately, there is little you can do to improve performance beause all the comparisons are inequalities.

You could just use string functions LEFT() and RIGHT() to check if the string starts or ends with a space, like:
SELECT *
FROM DummyTable
WHERE
(LEFT(Code, 1) = ' ' OR RIGHT(Code, 1) = ' ')
AND StartDate <= getdate()
AND EndDate > getdate()
AND CodeTypeID <> 27
ORDER BY 4 desc
As commented by Martin Smith, (LEFT(Code, 1) = ' ' OR RIGHT(Code, 1) = ' ') can be simplified as ' ' IN (LEFT(Code, 1), RIGHT(Code, 1)).
NB: few simplifications in your query:
you don't need to prefix the columns with the table name, since only one table is involved in the query
you don't need to surround individual conditions with parenthesis (just make sure to surround the ORed conditions with parenthesis to separate them from the ANDed conditions

Related

RIGHT of CHARINDEX not selecting correctly

I am trying to parse out a last name field that may have two last names that are separated by either a blank space ' ' or a hyphen '-' or it may only have one name.
Here is what I'm using to do that:
select top 1000
BENE_FIRST_NAME,
BENE_LAST_NAME,
FirstNm =
case
when BENE_FIRST_NAME like '% %' then
left(BENE_FIRST_NAME, CHARINDEX(' ', BENE_FIRST_NAME))
when BENE_FIRST_NAME like '%-%' then
left(BENE_FIRST_NAME, CHARINDEX('-', BENE_FIRST_NAME))
else BENE_FIRST_NAME
end,
LastNm =
case
when BENE_LAST_NAME like '% %' then
right(BENE_LAST_NAME, CHARINDEX(' ', BENE_LAST_NAME))
when BENE_LAST_NAME like '%-%' then
right(BENE_LAST_NAME, CHARINDEX('-', BENE_LAST_NAME))
else BENE_LAST_NAME
end,
CharIndxDash = CHARINDEX('-', BENE_LAST_NAME),
CharIndxSpace = CHARINDEX(' ', BENE_LAST_NAME)
from xMIUR_Elig_Raw_v3
Here are some results:
BENE_FIRST_NAME
BENE_LAST_NAME
FirstNm
LastNm
CharIndxDash
CharIndxSpace
JUANA
PEREZ-MARTINEZ
JUANA
RTINEZ
6
0
EMILIANO
PICENO ESPINOZA
EMILIANO
SPINOZA
0
7
JULIAN
NIETO-CARRENO
JULIAN
ARRENO
6
0
EMILY
SALMERON TERRIQUEZ
EMILY
TERRIQUEZ
0
9
The CHARINDEX seems to be selecting the correct position but it is not bringing in all of the CHARs to the right of that position. Sometimes it works like in the last record. But sometimes it is off by 1. And sometimes it is off by 2. Any ideas?
If you need to select part of a last name after space/hyphen, you need to get right part of the string with length = total_lenght - space_position:
...
LastNm =
case
when BENE_LAST_NAME like '% %' then
right(BENE_LAST_NAME, LEN(BENE_LAST_NAME) - CHARINDEX(' ', BENE_LAST_NAME))
when BENE_LAST_NAME like '%-%' then
right(BENE_LAST_NAME, LEN(BENE_LAST_NAME) -CHARINDEX('-', BENE_LAST_NAME))
else BENE_LAST_NAME
end,
...
Your last name logic doesn't make sense..
RIGHT takes N chars from the right of the string
CHARINDEX gives the position of a char from the left of the string
You can't use it to find a position from left and then take that number of chars from the right of the string
Here's a name:
JOHN MALKOVICH
The space is at 5. If you take 5 chars from the right, you get OVICH. The shorter the name before the space and the longer the name after the space, the fewer chars you get from the last name
Perhaps you mean to put a LEN in there so you take the string length minus the index of the space.. You can also use it in a call to SUBSTRING as the start index, and tell SQLS to take 9999 chars (of any number longer than the remaining string) and it will take up to the end of the string
SUBSTRING(name, CHARINDEX(' ', name)+1, 9999)
I think you can simplify your code by a lot. Consider below with a different but representative sample data
with data (name) as
(select 'first-last' union select 'first last' union select 'firstlast'),
data_prepped (name, indx) as
(select name,coalesce(nullif(charindex(' ', name)+charindex('-', name),0),len(name))
from data)
select name,
left(name, indx-1) as part1,
right(name, indx) as part2
from data_prepped

display the length of the first word of a dataset

Hi I'm having problems trying to switch the output of the FirstWordLength to print the amount of characters in each first word this output to
SELECT InvoiceLineItemDescription,
LEFT(InvoiceLineItemDescription,
CASE
WHEN charindex(' ', InvoiceLineItemDescription) = 0 THEN LEN(InvoiceLineItemDescription)
ELSE charindex(' ', InvoiceLineItemDescription) - 1 END)
AS FirstWordLength
FROM InvoiceLineItems
ORDER BY FirstWordLength desc;
It should look something like this:
InvoiceLineItemDescription FirstWordLength
citi bank 4
You can get the first word length using charindex():
SELECT InvoiceLineItemDescription,
CHARINDEX(' ', InvoiceLineItemDescription + ' ') - 1 as FirstWordLength
FROM InvoiceLineItems
ORDER BY FirstWordLength desc;
As in your question, this assumes that only spaces are used for delimiting words. You can use PATINDEX() to support more separator characters.
The case in your code should work, but you are using it to extract the first word, rather than just the length.

Checking a DateTime which is part of a larger nvarchar

I have a table, let's call it 'tblData'. which has a field called 'details' which is a nvarchar(4000). in this field there might be a text like such :
'blah blah ## 12/08/1982 ## blah blah'. the part that starts and ends in '##' might or might not exist.
I need to make a select statement with a where clause which will not return a row that has '## [date] ##' that is in the future. if the '## [date] ##' part does not exist, return the row.
is this possible to do without using a function?
and if I have to use a function, some sample code could come in handy as I barely know any tsql...
10x alot!
This is quite difficult to do in SQL. You can do it, by extracting the date, and converting it. But, SQL Server does not have great string manipulation functions.
The following extracts the date:
(case when details like '% [0-9]0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %'
then substring(details,
patindex('% [0-9]0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %',
details) + 1, 10)
end)
So, you can put this into a where clause as:
where details not like '% [0-9]0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %' or
convert(date,
(case when details like '% [0-9]0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %'
then substring(details,
patindex('% [0-9]0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %',
details) + 1, 10),
end), 101) <= getdate();
select * from tblData where details not like '%## ??/??/???? ##%'

How to remove the begining and ending characters if those are '0' in SQL Server

I currently have a table named DATA it has entries like the following:
abc000
ab000cde
000abc
I just want to remove all 0 from beginning and the end. If 0 comes in between the character then it will remain same.
This also works for leading and trailing zeros at the same time:
declare #s varchar(15) = '00abc00efg000'
select substring(#s,
patindex('%[^0]%', #s),
len(#s)-patindex('%[^0]%', reverse(#s))-patindex('%[^0]%', #s)+2);
Description: this is substring from first nonzero symbol till first nonzero symbol in reversed string.
Say your data exists in column called Col1, then this expression should do it
select CASE
WHEN RIGHT(col1 , 1) = '0'
THEN SUBSTRING(col1,0,PATINDEX('%[A-Z1-9]%',REVERSE(col1)))
WHEN LEFT(col1 , 1) = '0'
THEN SUBSTRING(col1,PATINDEX('%[A-Z1-9]%',col1),LEN(col1))
ELSE
Col1
END AS 'ParsedCol1'
FROM Data
I use this trick:
SELECT
REPLACE(REPLACE(RTRIM(LTRIM(REPLACE(REPLACE(col1, ' ', CHAR(8)), '0', ' '))), ' ', '0'), CHAR(8), ' ')
FROM
yourTable
This may works for SQL, as this removes leading & trailing "000" from your string.
SELECT TRIM(BOTH ‘000’ FROM
‘your_data_table_column’);
See more
http://www.mydigitallife.info/remove-or-trim-first-or-last-few-characters-in-mysql-database-with-sql/
http://www.w3resource.com/mysql/string-functions/mysql-trim-function.php

SQL Server : find percentage match of LIKE string

I'm trying to write a query to find the percentage match of a search string in a notes or TEXT column.
This is what I'm starting with:
SELECT *
FROM NOTES
WHERE UPPER(NARRATIVE) LIKE 'PAID CALLED RECEIVED'
Ultimately, what I want to do is:
Split the search string by spaces and search individually for all words in the string
Order the results descending based on percentage match
For example, in the above scenario, each word in the search string would constitute 33.333% of the total. A NARRATIVE with 3 matches (100%) should be at the top of the results, while a match containing 2 of the keywords (66.666%) would be lower, and a match containing 1 of the keywords (33.333%) would be even lower.
I then want to display the resulting percentage match for that row in a column, along with all the other columns from that table (*).
Hopefully, this makes sense and can be done. Any thoughts on how to proceed? This MUST all be done in SQL Server, and I would prefer not to write any CTEs.
Thank you in advance for any guidance.
Here is what I came up with:
DECLARE #VISIT VARCHAR(25) = '999232'
DECLARE #KEYWORD VARCHAR(100) = 'PAID,CALLED,RECEIVED'
DECLARE SPLIT_CURSOR CURSOR FOR
SELECT RTRIM(LTRIM(VALUE)) FROM Rpt_Split(#KEYWORD, ',')
IF OBJECT_ID('tempdb..#NOTES_FF_SEARCH') IS NOT NULL DROP TABLE #NOTES_FF_SEARCH
SELECT N.VISIT_NO
,N.CREATE_DATE
,N.CREATE_BY
,N.NARRATIVE
,0E8 AS PERCENTAGE
INTO #NOTES_FF_SEARCH
FROM NOTES_FF AS N
WHERE N.VISIT_NO = #VISIT
DECLARE #KEYWORD_VALUE AS VARCHAR(255)
OPEN SPLIT_CURSOR
FETCH NEXT FROM SPLIT_CURSOR INTO #KEYWORD_VALUE
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE #NOTES_FF_SEARCH
SET PERCENTAGE = PERCENTAGE + ( 100 / ##CURSOR_ROWS )
WHERE UPPER(NARRATIVE) LIKE '%' + UPPER(#KEYWORD_VALUE) + '%'
FETCH NEXT FROM SPLIT_CURSOR INTO #KEYWORD_VALUE
END
CLOSE SPLIT_CURSOR
DEALLOCATE SPLIT_CURSOR
SELECT * FROM #NOTES_FF_SEARCH
WHERE PERCENTAGE > 0
ORDER BY PERCENTAGE, CREATE_DATE DESC
There may be a more efficient way to do this but every other road I started down ended in a dead-end. Thanks for your help
If you want to do a "percentage" match, you need to do two things: calculate the number of words in the string and calculate the number of words you care about. Before giving some guidance, I will say that full text search probably does everything you want and much more efficiently.
Assuming the search string has space delimited words, you can count the words with the expression:
(len(narrative) - len(replace(narrative, ' ', '') + 1) as NumWords
You can count the matching words with success replaces. So, for keywords, it would be something like removing each key word, fixing the spaces, and counting the words.
The overall code is best represented with subqueries. The resulting query is something like:
select n.*
from (select n.*,
(len(narrative) - len(replace(narrative, ' ', '') + 1.0) as NumWords,
ltrim(rtrim(replace(replace(replace(narrative + ' ', #keyword1 + ' ', ''),
#keyword2 + ' ', ''),
#keyword3 + ' ', ''))) as NoKeywords
from notes n
) n
order by 1 - (len(NoKeywords) - len(replace(NoKeywords, ' ', '') + 1.0) / NumWords desc;
SQL Server -- as with many databases -- is not particularly good at parsing strings. You can do that outside the query and assign the #keyword variables accordingly.