Trying to combine three individual SELECT statements into one main SELECT statement - sql

Here's the problem. There are 3 fields in my table which may contain data with an extra quotation appended at the end. So, I'm trying to run a select statement that will remove this extra character from these fields, IF that extra character exists. I can write 3 individual queries just fine, and they work, but I'm trying to combine them all into one query. Here's what I have so far, and I know it's probably incorrect the way I have it:
Here's the result set that comes back. Notice that all three columns are NULL. They shouldn't be:
Here's an individual query that works for one field at a time:
Can you tell me what I'm doing wrong?

You can remove the WHEREs, as well as the non-correlated subqueries in the select list, and probably simplify it to this...
SELECT
AID
, EID
, STOREID
, [Language]
, 'BrandLabel' = CASE WHEN BrandLabel LIKE '%"'
THEN LEFT(BrandLabel, LEN(BrandLabel) -1)
ELSE BrandLabel
END
, 'Terms' = CASE WHEN Terms LIKE '%"'
THEN LEFT(Terms, LEN(Terms) -1)
ELSE Terms
END
, 'TrackOrderLbl' = CASE WHEN TrackOrderLbl LIKE '%"'
THEN LEFT(TrackOrderLbl, LEN(TrackOrderLbl) -1)
ELSE TrackOrderLbl
END
FROM parallel_Purchase_Email_Content_OMS WITH (NOLOCK)

Related

Return Condition/Expression from a Case Statement

I have searched all around and cannot seem to find a solution to this problem I'm having. I have a fairly large case statement (over 100 lines) that works and returns the result I am looking for. An example of the line is below:
case
When (Description like '%job%'
or description like '%job%fail%') then 'Job'
Else 'Not Classified'
End as ATC
I have a case statement that returns the result 'Job' as expected. I would also like to create a separate case statement that returns the criteria that returns the condition that the record met, allowing me to evaluate which criteria are returning the match ( a 'job' vs. 'job failed' comparison). I'm aware that I can duplicate my case statement to output the criteria met, but I would like to repeat this analysis and am looking for a more easily replicable solution (something along the lines of reading the conditions from the above case statement). Any thoughts?
If you're just trying to avoid repeating the logic you can wrap it up in a table expression.
with matches as (
select *,
case when Description like '%job%fail%' then 1 -- most specific first
when Description like '%job%' then 2 -- least specific last
else 0
end as MatchCode
from ...
)
select *,
case when MatchCode > 0 then 'Job' Else 'Not Classified' End as ATC
from matches

REPLACE not doing what I need in SQL

I've got a query pulling data from a table. In one particular field, there are several cases where it is a zero, but I need the four digit location number. Here is where I'm running into a problem. I've got
SELECT REPLACE(locationNbr, '0', '1035') AS LOCATION...
Two issues -
Whoever put the table together made all fields VARCHAR, hence the single quotes.
In the cases where there already is the number 1035, I get 1103535 as the location number because it's replacing the zero in the middle of 1035.
How do I select the locationNbr field and leave it alone if it's anything other than zero (as a VARCHAR), but if it is zero, change it to 1035? Is there a way to somehow use TO_NUMBER within the REPLACE?
SELECT CASE WHEN locationNbr='0' THEN '1035' ELSE locationNbr END AS LOCATION...
REPLACE( string, string_to_replace , replacement_string )
REPLACE looks for a string_to_replace inside a string and replaces it with a replacent_string. That is why you get the undesired behaviour - you are using the wrong function.
CASE WHEN condition THEN result1 ELSE result2 END
CASE checks a condition and if it is true it returns result1 and if it is not it will return result2. This is a simple example, you can write a case statement with more than one condition check.
Don't use replace(). Use case:
(case when locationNbr = '0' then '1035' else locationNbr end)
You can make use of length in Oracle:
select case when length(loacation) = 1 then REPLACE(loacation, '0', '1035') else loacation end as location
from location_test;

How can I compare two columns for similarity in SQL Server?

I have one column that called 'message' and includes several data such as fund_no, detail, keywords. This column is in table called 'trackemails'.
I have another table, called 'sendemails' that has a column called 'Fund_no'.
I want to retrieve all data from 'trackemail' table that the column 'message' contains characters same as 'Fund_no' in 'trackemails' Table.
I think If I want to check the equality, I would write this code:
select
case when t.message=ts.fund_no then 1 else 0 end
from trackemails t, sendemails s
But, I do want something like below code:
select
case when t.message LIKE ts.fund_no then 1 else 0 end
from trackemails t, sendemails s
I would be appreciate any advice to how to do this:
SELECT *
FROM trackemails tr
INNER JOIN sendemail se on tr.Message like '%' + se.Fund_No + '%'
Dear Check SQL CHARINDEX() Function. This function finds a string in another string and returns int for the position they match. Like
SELECT CHARINDEX('ha','Elham')
-- Returns: 3
And as you need:
SELECT *
,(SELECT *
FROM sendemail
WHERE CHARINDEX(trackemails.Message,sendemail.Fund_No)>0 )
FROM trackemails
For more information, If you want something much better for greater purposes, you can use Fuzzy Lookup Component in SSDT SSIS. This Component gives you a new column in the output which shows the Percentages of similarity of two values in two columns.

SQL CASE returning two values

I'm writing my first SQL CASE statement and I have done some research on them. Obviously the actual practice is going to be a little different than what I read because of context and things of that nature. I understand HOW they work. I am just having trouble forming mine correctly. Below is my draft of the SQL statement where I am trying to return two values (Either a code value from version A and it's title or a code value from version B and its title). I've been told that you can't return two values in one CASE statment, but I can't figure out how to rewrite this SQL statement to give me all the values that I need. Is there a way to use a CASE within a CASE (as in a CASE statement for each column)?
P.S. When pasting the code I removed the aliases just to make it more concise for the post
SELECT
CASE
WHEN codeVersion = A THEN ACode, Title
ELSE BCode, Title
END
FROM Code.CodeRef
WHERE ACode=#useCode OR BCode=#useCode
A case statement can only return one value. You can easily write what you want as:
SELECT (CASE WHEN codeVersion = 'A' THEN ACode
ELSE BCode
END) as Code, Title
FROM Code.CodeRef
WHERE #useCode in (ACode, BCode);
A case statement can only return a single column. In your scenario, that's all that is needed, as title is used in either outcome:
SELECT
CASE
WHEN codeVersion = "A" THEN ACode,
ELSE BCode
END as Code,
Title
FROM Code.CodeRef
WHERE ACode=#useCode OR BCode=#useCode
If you actually did need to apply the case logic to more than one column, then you'd need to repeat it.
Here is what I normally use:
SELECT
CASE
WHEN codeVersion = "A" THEN 'ACode'
WHEN codeVersion = "B" THEN 'BCode'
ELSE 'Invalid Version'
END as 'Version',
Title
FROM Code.CodeRef
WHERE
CASE
WHEN codeVersion = "A" THEN ACode
WHEN codeVersion = "B" THEN BCode
ELSE 'Invalid Version'
END = 'Acode'
my suggestion uses an alias. note on aliases: unfortunately you can't use the alias 'Version' in a where/group by clause. You have to use the whole case statement again. I believe you can only use an alias in an Order By.

how can I force SQL to only evaluate a join if the value can be converted to an INT?

I've got a query that uses several subqueries. It's about 100 lines, so I'll leave it out. The issue is that I have several rows returned as part of one subquery that need to be joined to an integer value from the main query. Like so:
Select
... columns ...
from
... tables ...
(
select
... column ...
from
... tables ...
INNER JOIN core.Type mt
on m.TypeID = mt.TypeID
where dpt.[DataPointTypeName] = 'TheDataPointType'
and m.TypeID in (100008, 100009, 100738, 100739)
and datediff(d, m.MeasureEntered, GETDATE()) < 365 -- only care about measures from past year
and dp.DataPointValue <> ''
) as subMdp
) as subMeas
on (subMeas.DataPointValue NOT LIKE '%[^0-9]%'
and subMeas.DataPointValue = cast(vcert.IDNumber as varchar(50))) -- THIS LINE
... more tables etc ...
The issue is that if I take out the cast(vcert.IDNumber as varchar(50))) it will attempt to compare a value like 'daffodil' to a number like 3245. Even though the datapoint that contains 'daffodil' is an orphan record that should be filtered out by the INNER JOIN 4 lines above it. It works fine if I try to compare a string to a string but blows up if I try to compare a string to an int -- even though I have a clause in there to only look at things that can be converted to integers: NOT LIKE '%[^0-9]%'. If I specifically filter out the record containing 'daffodil' then it's fine. If I move the NOT LIKE line into the subquery it will still fail. It's like the NOT LIKE is evaluated last no matter what I do.
So the real question is why SQL would be evaluating a JOIN clause before evaluating a WHERE clause contained in a subquery. Also how I can force it to only evaluate the JOIN clause if the value being evaluated is convertible to an INT. Also why it would be evaluating a record that will definitely not be present after an INNER JOIN is applied.
I understand that there's a strong element of query optimizer voodoo going on here. On the other hand I'm telling it to do an INNER JOIN and the optimizer is specifically ignoring it. I'd like to know why.
The problem you are having is discussed in this item of feedback on the connect site.
Whilst logically you might expect the filter to exclude any DataPointValue values that contain any non numeric characters SQL Server appears to be ordering the CAST operation in the execution plan before this filter happens. Hence the error.
Until Denali comes along with its TRY_CONVERT function the way around this is to wrap the usage of the column in a case expression that repeats the same logic as the filter.
So the real question is why SQL would be evaluating a JOIN clause
before evaluating a WHERE clause contained in a subquery.
Because SQL engines are required to behave as if that's what they do. They're required to act like they build a working table from all of the table constructors in the FROM clause; expressions in the WHERE clause are applied to that working table.
Joe Celko wrote about this many times on Usenet. Here's an old version with more details.
First of all,
NOT LIKE '%[^0-9]%'
isn`t work well. Example:
DECLARE #Int nvarchar(20)= ' 454 54'
SELECT CASE WHEN #INT LIKE '%[^0-9]%' THEN 1 ELSE 0 END AS Is_Number
Result: 1
But it is not a number!
To check if it is real int value , you should use ISNUMERIC function. Let`s check this:
DECLARE #Int nvarchar(20)= ' 454 54'
SELECT ISNUMERIC(#int) Is_Int
Result:0
Result is correct.
So, instead of
NOT LIKE '%[^0-9]%'
try to change this to
ISNUMERIC(subMeas.DataPointValue)=0
UPDATE
How check if value is integer?
First here:
WHERE ISNUMERIC(str) AND str NOT LIKE '%.%' AND str NOT LIKE '%e%' AND str NOT LIKE '%-%'
Second:
CREATE Function dbo.IsInteger(#Value VarChar(18))
Returns Bit
As
Begin
Return IsNull(
(Select Case When CharIndex('.', #Value) > 0
Then Case When Convert(int, ParseName(#Value, 1)) <> 0
Then 0
Else 1
End
Else 1
End
Where IsNumeric(#Value + 'e0') = 1), 0)
End
Filter out the non-numeric records in a subquery or CTE