sql postcode space - sql

Im trying to make it so that no matter how long the postcode is its always has a space before the last 3 characters. Sometimes i will receive postcodes and people have only typed in 4 characters so code like this :
UPDATE [DataTool].[dbo].[EH10414 Summer Events]
SET postcode = CASE WHEN LEN(postcode) = 6 THEN STUFF(postcode, 4, 0, ' ')
WHEN LEN(postcode) = 7 THEN STUFF(postcode, 5, 0, ' ')
END
WHERE CHARINDEX(' ', postcode, 1) = 0
AND LEN(postcode) BETWEEN 6 AND 7
Isnt really much use. I got this of this site it does work but not what im looking for. Im pretty new to SQL but in access i can use this:
Update to: Left([PostCode],Len([PostCode])-3) & " " & Right([PostCode],3)
This works perfectly but i dont know how to implement this into SQL.
any help would be great :)
Thanks

Your Access code will pretty much work in SQL Server:
Left(PostCode, Len(PostCode) - 3) + ' ' + Right(PostCode, 3)
I would check first that a space is not there:
(case when PostCode like '% ___' then PostCode
else Left(PostCode, Len(PostCode) - 3) + ' ' + Right(PostCode, 3)
end)

One way to implement this into SQL (with some minor tweaks to get the syntax right for SQL Server) would be to create a user defined function taking an input Postcode, and returning a new version with a space added:
CREATE FUNCTION SpacePostcode ( #inputPostcode VARCHAR(8) )
RETURNS VARCHAR(8)
BEGIN
RETURN Left(#inputPostcode ,Len(#inputPostcode)-3) + ' ' + Right(#inputPostcode,3)
END
GO
This could then be used in a select statement to format output such as
SELECT dbo.fnSpacePostcode('EH78PP') AS postCode
or to update existing data using an update statement such as
UPDATE myTable
SET PostCode = dbo.fnSpacePostcode(PostCode)

Related

How to count words in specific column against matching words in another table

I want to be able to:
extract specific words from column1 in Table1 - but only the words that are matched from Table2 from a column called word,
perform a(n individual) count of the number of words that have been found, and
put this information into a permanent table with a format, that looks like:
Final
Word | Count
--------+------
Test | 7
Blue | 5
Have | 2
Currently I have tried this:
INSERT INTO final (word, count)
SELECT
extext
, SUM(dbo.WordRepeatedNumTimes(extext, 'test')) AS Count
FROM [dbo].[TestSite_Info], [dbo].[table_words]
WHERE [dbo].[TestSite_Info].ExText = [dbo].[table_words].Words
GROUP BY ExText;
The function dbo.WordRepeatedNumTimes is:
ALTER function [dbo].[WordRepeatedNumTimes]
(#SourceString varchar(8000),#TargetWord varchar(8000))
RETURNS int
AS
BEGIN
DECLARE #NumTimesRepeated int
,#CurrentStringPosition int
,#LengthOfString int
,#PatternStartsAtPosition int
,#LengthOfTargetWord int
,#NewSourceString varchar(8000)
SET #LengthOfTargetWord = len(#TargetWord)
SET #LengthOfString = len(#SourceString)
SET #NumTimesRepeated = 0
SET #CurrentStringPosition = 0
SET #PatternStartsAtPosition = 0
SET #NewSourceString = #SourceString
WHILE len(#NewSourceString) >= #LengthOfTargetWord
BEGIN
SET #PatternStartsAtPosition = CHARINDEX (#TargetWord,#NewSourceString)
IF #PatternStartsAtPosition <> 0
BEGIN
SET #NumTimesRepeated = #NumTimesRepeated + 1
SET #CurrentStringPosition = #CurrentStringPosition + #PatternStartsAtPosition +
#LengthOfTargetWord
SET #NewSourceString = substring(#NewSourceString, #PatternStartsAtPosition +
#LengthOfTargetWord, #LengthOfString)
END
ELSE
BEGIN
SET #NewSourceString = ''
END
END
RETURN #NumTimesRepeated
END
When I run the above INSERT statement, no record is inserted.
In the table TestSite_Info is a column called Extext. Within this column, there is random text - one of the words being 'test'.
In the other table called Table_Words, I have a column called Words and one of the words in there is 'Test'. So in theory, as the word is a match, I would pick it up, put it into the table Final, and then next to the word (in another column) the count of how many times the word has been found within TestSite_Info.Extext.
Table_Words
id|word
--+----
1 |Test
2 |Onsite
3 |Here
4 |As
TestSite_Info
ExText
-------------------------------------------------
This is a test, onsite test , test test i am here
The expected Final table has been given at the top.
-- Update
Now that I have run Abecee block of code this actually works in terms of bringing back a count column and the id relating to the word.
Here are the results :
id|total
--+----
169 |3
170 |0
171 |5
172 |7
173 |1
174 |3
Taken from the following text which it is extracting from :
Test test and I went to and this was a test I'm writing rubbish hello
but I don't care about care and care seems care to be the word that you will see appear
four times as well as word word word word word, but a .!
who knows whats going on here.
So as you can see, the count for ID 172 appears 7 times (as a reference please see below to what ID numbers relate to in terms of words) which is incorrect it should appear appear 6 times (its added +1 for some reason) as well as ID 171 which is the word care, that appears 4 times but is showing up as 5 times on the count. Any ideas why this would be?
Also what I was really after was a way as you have quite kindly done of the table showing the ID and count BUT also showing the word it relates to as well in the final table, so I don't have to link back through the ID table to see what the actual word is.
Word|id
--+----
as |174
here |173
word |172
care |171
hello |170
test |169
You could work along the updated
WITH
Detail AS (
SELECT
W.id
, W.word
, T.extext
, (LEN(REPLACE(T.extext, ' ', ' ')) + 2
- LEN(REPLACE(' '
+ UPPER(REPLACE(REPLACE(REPLACE(REPLACE(T.extext, ' ', ' '), ':', ' '), '.', ' '), ',', ' '))
+ ' ', ' ' + UPPER(W.word) + ' ', '')) - 1
) / (LEN(W.word) + 2) count
FROM Table_Words W
JOIN TestSite_Info T
ON CHARINDEX(UPPER(W.word), UPPER(T.extext)) > 0
)
INSERT INTO Result
SELECT
id
, SUM(count) total
FROM Detail
GROUP BY id
;
(Had forgotten to count in the blanks added to the front and the end, missed a sign change, and got mixed up as for the length of the word(s) surrounded by blanks. Sorry about that. Thanks for testing it more thoroughly than I did originally!)
Tested on SQL Server 2008: Updated SQL Fiddle and 2012: Updated SQL Fiddle.
And with your test case as well.
It:
is pure SQL (no UDF required),
has room for some tuning:
Store words all lower / all upper case, unless case matters (Which would require to adjust the suggested solution.)
Store strings to check with all punctuation marks removed.
Please comment if and as further detail is required.
From what I could understand, this might do the job. However, things will be more clear if you post the schema
create table final(
word varchar(100),
count integer
);
insert into final (word, count)
select column1, count(*)
from table1, table2
where table1.column1 = table2.words
group by column1;
Thanks for all your help.
The best approach for this solution was :
WITH
Detail AS (
SELECT
W.id
, W.word
, T.extext
, (LEN(REPLACE(T.extext, ' ', ' ')) + 2
- LEN(REPLACE(' '
+ UPPER(REPLACE(REPLACE(REPLACE(REPLACE(T.extext, ' ', ' '), ':', ' '), '.', ' '), ',', ' '))
+ ' ', ' ' + UPPER(W.word) + ' ', '')) - 1
) / (LEN(W.word) + 2) count
FROM Table_Words W
JOIN TestSite_Info T
ON CHARINDEX(UPPER(W.word), UPPER(T.extext)) > 0
)
INSERT INTO Result
SELECT
id
, SUM(count) total
FROM Detail
GROUP BY id
Re-reading the problem description, the presented SELECT seems to try to align/join full "exText" strings with individual "words" - but based on equality. Then, it has "exText" in the SELECT list whilst "Result" seems to wait for individual words. (That would not fail the INSERT, though, as long as the field is not guarded by a foreign key constraint. But as the WHERE/JOIN is not likely to let any data through, this is probably never coming up as an issue anyway.)
For an alternative to the pure declarative approach, you might want to try along
INSERT INTO final (word, count)
SELECT
word
, SUM(dbo.WordRepeatedNumTimes(extext, word)) AS Count
FROM [dbo].[TestSite_Info], [dbo].[table_words]
WHERE CHARINDEX(UPPER([dbo].[table_words].Word), UPPER([dbo].[TestSite_Info].ExText)) > 0
GROUP BY word;
You have "Word" in your "Table_Words" description - but use "[dbo].[table_words].Words" in your WHERE condition…

SQL - string comparison ignores space

This query:
SELECT CASE WHEN 'abc ' = 'abc' THEN 1 ELSE 0 END
Returns 1, even though 'abc ' clearly is not equal to 'abc'. Similarly,
SELECT CASE WHEN 'abc ' LIKE '%c' THEN 1 ELSE 0 END
Also returns 1. However, a very similar query:
SELECT * FROM #tempTable WHERE Name LIKE '%c'
Did not return a row where Name = 'abc '.
SQL Server 2008 R2, Windows 7 & 2008 R2, x64.
= ignores trailing space
len ignores training space
like does not ignore trailing space
SELECT CASE WHEN 'abc ' = 'abc' and DATALENGTH('abc ') = DATALENGTH('abc')
THEN 1 ELSE 0 END
You can assert DATALENGTH is not relevant but it is still the solution.
Turns out that the Name column was NVARCHAR (even though it contained ASCII characters only) and NVARCHAR behaves differently than VARCHAR:
SELECT CASE WHEN N'abc ' LIKE 'abc' THEN 1 ELSE 0 END
Returns 0, ditto for column instead of literal. The following does return 1 still:
SELECT CASE WHEN N'abc ' = 'abc' THEN 1 ELSE 0 END
So = and LIKE work differently, another peculiar difference.
If you need to compare things in this way but are restricted because your columns are of data type VARCHAR, something like this will basically fill the trailing space with an 'X' which will accomplish a failed comparison:
DECLARE #1 VARCHAR(5), #2 VARCHAR(5)
SET #1 = 'ABC '
SET #2 = 'ABC'
IF REPLACE(#1,' ','X') = REPLACE(#2,' ','X')
PRINT 'Equal'
ELSE
PRINT 'Not Equal'
Not rocket science, but at least a work around if you encounter a similar situation that you need to deal with :)
TA, I am not sure how you got zero by simply mentioning as unicode(N). I run your query and it giving me 1 only.
You can compare the LEN('abc ') and DATALENGTH('abc ') and can use those as per you requirement or you can replace the trailing space with some character to solve your problem.
I had a similar issue with a nvarchar column and wanted to fix the data so I did the following to find the data
select 'x' + username + 'x' from aspnet_users
where 'x' + username + 'x' <> 'x' + rtrim(username) + 'x'
The where clause compares the username as is with the trimmed version
'x1234 x' <> 'x1234x'
To fix the data I just did an update
update aspnet_Users
set username = rtrim(username)
where 'x' + username + 'x' <> 'x' + rtrim(username) + 'x'

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.

SQL Select Error When using Case

CASE WHEN PFW_Access__c = 1
THEN 'New Employee (' + New_Employee_Name__c + ') needs PFW Access'
ELSE ''
END AS PFWAccessDesc,`
The line above is just one of many lines in my select statement. It outputs correctly with New Employee (name) needs PFW Access. What I'm trying to do is to add another field to the output Description_Short__c but when I tried to add it to the statement I receive an error. I'm not sure how to add it in to the statement to show in the output.
is this waht you are after?
CASE WHEN PFW_Access__c = 1
THEN 'New Employee (' + ISNULL(New_Employee_Name__c,'') + ') needs PFW Access '
+ISNULL(Description_Short__c,'')
ELSE ''
END AS PFWAccessDesc,
If I remember correctly from a previous question, Description_Short__c is a text field in your database. If you're trying to do just about anything w/ this column, you're going to have to use cast(Description_Short__c as varchar(max)) instead of Description_Short__c.

SQL Server 2005- Add area code to records shorter than 10 characters

Can anyone come up with a SQL routine or ideas to systematically append an area code to the beginning of every field in our SQL Server 2005 database that does not have an area code in it?
Perhaps someone could tell us how to return only rows that are less than 10 characters long and how to append the 3 digit area code to the beginning of each field string?
Thanks!
DECLARE #AreaCode char(3)
SET #AreaCode = 'XXX'
UPDATE myTable
SET myField = #AreaCode + myField
WHERE LEN(myField) < 10
AND myField NOT LIKE #AreaCode + '%'
This will work with SQL Server.
Ideally, the area code would be a separate column in your database. Since it's not designed that way though:
UPDATE
PhoneNumbers
SET
phone_number = '123' + phone_number
WHERE
LEN(phone_number) = 7
Of course, if people have formatted the phone numbers then this won't work. I would need to know more about the data that's in your table. You might have to do something like:
UPDATE
PhoneNumbers
SET
phone_number = '(123) ' + phone_number
WHERE
LEN(REPLACE(REPLACE(REPLACE(REPLACE(phone_number, '-', ''), '(', ''), ')', ''), '.', '') = 7
If people typed in stuff like "ext. 7" then that would further complicate things. See why it's better to break out a phone number instead of just having one column? ;)