SQL Replace Not working for Greater Than > - sql

I'm trying to count all values in a column Value that are over 5.
However, some results in that column appear like '>10' (it has the greater than symbol > in the field)
I'd like to still count that as > 5.
To do that, I did the following:
(COUNT(CASE WHEN t.VALUE LIKE '*>*'
and Replace(t.VALUE, '>', ' ') > 5)
Then 1
Else NULL
End
)
But, for whatever reason, it's not replacing.

Well, how about converting to a number?
select sum(case when try_convert(int, replace(t.value, '>', '')) > 5
then 1 else 0
end) as values_over_5
Your data model is suspicious, because you are doing numeric comparisons on a column that contains numbers.

A couple of things.
The asterisk isn't a valid wildcard character in SQL Server, so we'll change that.
Also, if you want the string to become a number, you'll want to replace the greater-than with an empty string, not a space. It doesn't affect the outcome, but it's the right thing to do.
This isn't as elegant as Gordon's one-liner, but it produced the expected results.
DECLARE #t TABLE (VALUE VARCHAR(5));
INSERT #t (VALUE)
VALUES ('1'),('10'),('>10');
SELECT COUNT(*) AS Over5
FROM
(
SELECT
CASE WHEN t.VALUE LIKE '%>%' THEN Replace(t.VALUE, '>', '')
ELSE t.VALUE
END AS NewVal
FROM #t as t
) AS d
WHERE NewVal > 5;
+-------+
| Over5 |
+-------+
| 2 |
+-------+

Related

Show all numbers that are not in table

I have the following problem.
I have more than 60,000 numbers in my DB2 database and I need to check which of them are not found in my table.
I would like to have the output as follows:
number | found | not-found
010012 |x |
010023 | |x
Depending on that I have to create either an UPDATE or an INSERT.
I already created the UPDATE statement with all the numbers. That`s not the problem, however, finding out which of the numbers are missing or not I cannot figure it out.
This is my SELECT which of course does not work as expected.
SELECT
a.Field1 || a.Field2,
CASE WHEN a.Field1 || a.Field2 IN ('010012', '010023')
THEN 'Found'
ELSE 'None'
END
FROM TEST_TABLE.U56 a
WHERE Field1 || Field2 IN ('010012', '010023');
Try this:
WITH
NUMBERS (NUMBER) AS
(
VALUES
'010012'
, '010023'
)
,
MY_TABLE (NUMBER) AS
(
VALUES
'010012'
, '010012'
)
SELECT DISTINCT
N.NUMBER
, CASE WHEN T.NUMBER IS NOT NULL THEN 'x' END AS FOUND
, CASE WHEN T.NUMBER IS NULL THEN 'x' END AS NOT_FOUND
FROM NUMBERS N
LEFT JOIN MY_TABLE T ON T.NUMBER = N.NUMBER
NUMBER
FOUND
NOT_FOUND
010023
x
010012
x
If it's not what you need, then please, edit your question with a complete example with sample data for both tables and the result desired.

Can't get a correct sort with SQL Server 2008

I have a table with returns such as 12X90, 12X120, 12X160, etc.
The numbers after the "X" are weights. I need to pad the weights only with leading zeros so that 90 become 090. A normal sort will put the 90 last instead of first, I need the list sorted correctly, by weight.
How can I achieve that?
Use charindex to get the number after X in the column and order by that number.
select * from tablename
order by cast(case when charindex('X',col) > 0 then substring(col,charindex('X',col)+1,len(col))
else col end as numeric)
If the string before X should also be considered for sorting, use
select * from tablename
order by
cast(case when charindex('X',col) > 0 then substring(col,1,charindex('X',col)-1)
else col end as numeric)
,cast(case when charindex('X',col) > 0 then substring(col,charindex('X',col)+1,len(col))
else col end as numeric)
Sample demo
use a cross apply
select
b.* from table t1
cross apply
(select replace(t.weight,'12x','') as replaced from table t2 where t2.weight=t1.weight) b
order by b.replaced

Return an INT from a Case statement

I am attempting to create a row called Flag that will keep a count of when Value is above 2. Later I will need to sum flag as a count.
I currently have:
CASE
WHEN Value > 2
THEN 1
ELSE 0
END AS 'Flag',
CASE
WHEN 'Flag' = 1
THEN 1
ELSE 0
END AS 'FollowedUpCorrectly'
I receive the error:
Conversion failed when converting the varchar value 'Flag' to data
type int.
How can I force the 1 or 0 to be an INT in order to do later math?
I've looked around and I can't seem to find a way that fits.
To be able to use previously created columns in the select, you'll need to use for example outer apply, with something like this:
select
*
from table1
outer apply (
select CASE WHEN Value > 2 THEN 1 ELSE 0 END AS Flag
) X
outer apply (
select CASE WHEN X.Flag = 1 THEN 1 ELSE 0 END AS FollowedUpCorrectly
) Y
Test this in SQL Fiddle
You could use CTE or a subquery to create a flag and then do your case statement as needed in the outer query like this:
;WITH q1
AS (
SELECT
col1
,col2
,col3
,CASE
WHEN Value > 2
THEN 1
ELSE 0
END AS 'Flag'
FROM your_table --change this to match your table and column name
)
SELECT q1.col1
,q1.col2
,q1.col3
,CASE
WHEN q1.Flag = 1
THEN 1
ELSE 0
END AS 'FollowedUpCorrectly'
FROM q1;
I might misunderstand what you are after.
CASE
WHEN Value > 2
THEN 1
ELSE 0
END AS 'Flag',
CASE
WHEN 'Flag' = 1
THEN 1
ELSE 0
END AS 'FollowedUpCorrectly'
If these two lines are in the same code block, 'Flag' is unknown in the second Case Statement.
Update: As Siyual has pointed out, Flag is a string literal. Try changing the name to something that is not a reserved word.
You are comparing a string ('Flag') to an int (1). Perhaps you meant to refer to the first case that you named 'Flag'. If so, try referring to it without using the single quotes. Then the analyzer will recognize it and accept it as an int, which it is. But 'Flag' is a string. Flag is an int.

select result set row to columns transformation

I've a table remarks with columns id, story_id, like like can be +1, -1
I want my select query to return the following columns story_id, total, n_like, n_dislike where total = n_like + n_dislike without sub queries.
I am currently doing a group by on like and selecting like as like_t, count(like) as total which is giving me an output like
-- like_t --+ --- total --
-1 | 2
1 | 6
and returning two rows in result set. But what I want is to get 1 row where n_like is 6 and n_dislike is 2 and total is 8
First, LIKE is a reserved word in PostgreSQL, so you have to double-quote it. Maybe a better name should be picked for this column.
CREATE TABLE testbed (id int4, story_id int4, "like" int2);
INSERT INTO testbed VALUES
(1,1,'+1'),(1,1,'+1'),(1,1,'+1'),
(1,1,'+1'),(1,1,'+1'),(1,1,'+1'),
(1,1,'-1'),(1,1,'-1');
SELECT
story_id,
sum(CASE WHEN "like" > 0 THEN abs("like") ELSE 0 END) AS n_like,
sum(CASE WHEN "like" < 0 THEN abs("like") ELSE 0 END) AS n_dislike,
count(story_id) AS total
-- for cases +2 / -3 in the "like" field, use following construct instead
-- sum(abs("like")) AS total
FROM testbed
GROUP BY story_id;
I used abs("like") for cases when you'll have +2 or -3 in your "like" column.

Can we have multiple case then statements in sql

I am trying for something which requires case within case I just wanted to make sure if we can use multiple case then?I am running this on sql teradata
The code I am trying to use is as below
AND(
case when CHARACTER_LENGTH(drug.n)=0 then 0
when CHARACTER_LENGTH(drug.n)=1 then
(case when substring(drug.n from 1,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end)
when CHARACTER_LENGTH(drug.n)=2 then
(case when substring(drug.n from 1,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end *
case when substring(drug.n from 2,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end )
when CHARACTER_LENGTH(drug.n)=3 then
(case when substring(drug.n from 1,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end *
case when substring(drug.n from 2,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end *
case when substring(drug.n from 3,1) in (''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'') then 1 else 0 end )=1
If somebody has better idea you can let me know. I cannot use isnumeric function.
Yes you can use nested CASE statements. No problems with that in Teradata
Okay -
To determine whether an arbitrary length string contains only numeric characters (or does not), you can use a recurive CTE.
Please note that I don't know whether or not your RDBMS actually supports recursive CTEs, but this is a potential solution. Also, I'm not sure of the performance implications - however, it does remove the multiple CASE effect (And why isn't that an actual numeric field, anyways?).
So... For a table that looks like this:
id ch
================
1 1234567890
2 asdg
This statement returns all rows that contain only numeric characters (of any length):
WITH splitstring (id, chard, start, orig) as (
SELECT id, SUBSTRING(ch, 1, 1), 1, ch
FROM chartable
UNION ALL
SELECT id, SUBSTRING(orig, start + 1, 1), start + 1, orig
FROM splitstring
WHERE LENGTH(orig) > start)
SELECT *
FROM chartest as a
WHERE NOT EXISTS (SELECT '1'
FROM splitstring as b
WHERE a.id = b.id
AND chard NOT BETWEEN '0' AND '9')
Without some of the larger context it's somewhat difficult to know exactly what you're trying to accomplish. However, this should be adaptable for your needs.
(As a side note, DB2 for the iSeries doesn't seem to support regex either...)