SQL Select Error When using Case - sql

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.

Related

Use a "case when in" expression where the list values are in a single field?

I'm using SQL Server and would like to check if todays day name is in a list of values in a single field/column.
An example of the column "start_days" contents is:
'Monday','Tuesday','Sunday'
'Thursday'
'Friday','Sunday'
'Tuesday','Sunday'
'Tuesday','Wednesday','Thursday','Friday'
The code I am trying to run on this is:
case
when datename(weekday,getdate()) in (start_days) then 1
else 0
end as today_flag
And the result is 0 for every row.
Am I doing something wrong here or is it just not possible to use a single field as a list of values in the statement?
As a starter: you should fix your data model and not store multiple values in a single column. Storing list of values in a database column basically defeats the purpopose of a relational database. Here is a related reading on that topic.
That said, here is one option using pattern matching:
case
when ',' + start_days + ',' like '%,' + datename(weekday,getdate()) + ',%' then 1
else 0
end as today_flag
If you really have single quotes around values within the list, then we need to include them in the match:
case
when ',' + start_days + ',' like '%,''' + datename(weekday,getdate()) + ''',%' then 1
else 0
end as today_flag
If the values always are weekdays, this can be simplified since there is no risk of overlapping values:
case
when start_days like '%''' + datename(weekday,getdate()) + '''%' then 1
else 0
end as today_flag
The right answer to the question is fixing your data modal. Storing multiple values like that will leads you to many issue and you're stuck on one right now.
Until that, you could use LIKE operaor to get the desired results as:
SELECT *, CASE WHEN
Value LIKE CONCAT('%', QUOTENAME(DATENAME(WEEKDAY,GETDATE()), ''''), '%')
THEN 1
ELSE 0
END
FROM
(
VALUES
('''Monday'',''Tuesday'',''Sunday'''),
('''Thursday'''),
('''Friday'',''Sunday'''),
('''Tuesday'',''Sunday'''),
('''Tuesday'',''Wednesday'',''Thursday'',''Friday''')
) T(Value)
Here is a db<>fiddle where you can see how it's working online.

System.FormatException: 24141: A number is expected at position 47 of the input. The input has )

I have a table in sqlserverdb which contains column name EntityType, EntityJson.In EntityJson column contains following json value,
{"EntityId":{"Type":"String","Value":"bf58bbc6-0a5a-b9e0-4fb6-5e55604a1b68"},"Name":{"Type":"string","Value":"GasAssets"},"TenantName":{"Type":"string","Value":"v2rdemo"},"TenantId":{"Type":"string","Value":"c091e548-b45a-49b4-b8ec-2cb5e27c7af6"},"EntityType":{"Type":"string","Value":"EntityAssets"},"CreatedBy":{"Type":"string","Value":""},"ModifiedBy":{"Type":"string","Value":""},"Created":{"Type":"string","Value":""},"Modified":{"Type":"string","Value":""},"Parent":{"Type":"string","Value":""},"LastChat":{"Type":"string","Value":""},"Latitude":{"Type":"string","Value":-33.3479019999504},"Longitude":{"Type":"string","Value":6.203906305532271}}
and EntityType column value is "EntityAssets".
On GeoServer I have written the following query
SELECT
geometry::STGeomFromText('POINT(' + CAST(JSON_VALUE(EntityJson, '$.Latitude.Value') As CHAR(20)) + ' ' + CAST(JSON_VALUE(EntityJson, '$.Longitude.Value') AS CHAR(20)) + ')', 4326) as geometria
FROM
dbo.Entities
where
EntityType = 'EntityAssets'
While previewing layer on click openlayer I'm getting same exception.
But Inside Microsoft Sql Server Mgmt Studio running it's working fine with where clause and if i remove where clause and Execute again Query without where clause getting same Exception on Sql Server Mgmt studio.
A number is expected at position 47 of the input. The input has ).
It's hard to be sure without seeing your data, but the error sounds like you have a row with no or empty Latitude.Value and Longitude.Value. You will get a very similar error by running this query:
SELECT
geometry::STGeomFromText('POINT(' + '' + ' ' + '' + ')', 4326) as geometria
FROM
dbo.Entities
This simulates your two CASTs returning empty strings.
See also this old question on MSDN.

sql postcode space

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)

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…

Issue With Apostrophe

I have a Proc that was coded in Dynamic SQl for one of my Application. It is using to search the Applicants with their last name. Right now it is searching applicants with either their first 2 digits of their last name or full last name. But i have a problem searching Applicants that have Apostrophe in their last name(Example O'Connor). If the client try to search applicant with O' or O'Connor it is throwing an error. They want to search every Applicant with or without Apostrophe in their last name. Please Help I tried everything, but its not working. Below is my search code that using in the Proc to pull applicants:
Add wildcards if necessary
if Rtrim(#FirstName) <> ''
begin
If(Len(#FirstName) < 30) and (CharIndex('%', #FirstName) = 0) and #FirstName != ''
Set #FirstName = char(39) + #FirstName + '%' + char(39)
end
if Rtrim(#LastName) <> ''
begin
If(Len(#LastName) < 60) and (CharIndex('%', #LastName) = 0) and #LastName != ''
Set #LastName = Char(39) + #LastName + '%' + char(39)
end
Now build dinamically the filter base on input parameters
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Rtrim(#LastName)
You need to escape the apostrophe in the input string (basically replace a single ' with two '') as you build your SQL string
You need to pay attention to this anywhere you choose to pass user input to a SQL server database as its a security issue (SQL Injection Attacks) c.f. Bobby Tables
if Rtrim(#LastName) <> ''
select #Where = #Where + ' and a.LastName like '+ Replace(Rtrim(#LastName),'''','''''') + ''
My suggestion is to write the query to contain an alternate column to be used for filtering with the apostrophe/single quote replaced by any special character such as a #. This allows you to leave the original column intact in case you want to display it.
To do that in SQL Server, you could do something like this:
Select
tbl.strName_Last,
REPLACE(tblOrder.strName_Last, '''','#')) as StrLastNameForFilter
....
Then change your code to filter based on this alternate column, and in the user-provided filter string, replace the apostrophe/single quote with the special character.