sql query to replace a range of integer values with a string? - sql

I have a column in sql server in which there are integer values, now i want to replace a range e.g values> 55 with a string 'Normal value' and values<55 replace with 'abnormal value', I have tried replace() function but it didn't work. any help please??

The query below doesn't do anything on the table but instead of displaying the value, it displays the equivalent string,
SELECT yourValue,
CASE WHEN yourValue > 55 THEN 'Normal' ELSE 'Abnormal' END
FROM tableName
SQLFiddle Demo
56 and up will be Normal
55 and down will be Abnormal

If the column allows NULLs then you could try:
SELECT t.ColA, CASE WHEN t.ColA >= 55 THEN 'Normal value' WHEN t.ColA < 55 THEN 'abnormal value' END
FROM MySchema.MyTable AS t
Example:
DECLARE #MyTable TABLE
(
ID INT IDENTITY(1,1) PRIMARY KEY,
ColA INT NULL
);
INSERT INTO #MyTable (ColA) VALUES(11);
INSERT INTO #MyTable (ColA) VALUES(111);
INSERT INTO #MyTable (ColA) VALUES(NULL);
SELECT t.ColA,
CASE
WHEN t.ColA >= 55 THEN 'Normal value'
WHEN t.ColA < 55 THEN 'abnormal value'
-- WHEN t.ColA IS NULL THEN NULL
END AS CaseWhen
FROM #MyTable AS t
Results:
ColA CaseWhen
----------- --------------
11 abnormal value
111 Normal value
NULL NULL

Related

How can I simplify this Query? I need to compare a temp variable value with a column value of multiple rows

I need to compare a temp variable value with a column value of multiple rows and perform Operations based on that.
| intSeqID | Value |
----------------------------
1 | 779.40
2 | 357.38
3 | NULL
4 | NULL
5 | NULL
6 | NULL
7 | NULL
8 | NULL
9 | NULL
10 | NULL
DECLARE #tmpRange NUMERIC(5,2)
SELECT #tmpRange = 636
Here I need to compare the value #tmpRange with Value from TABLE and perform operations based on it.
IF((#tmpRange < (select ISNULL(Value,0) from #tableA intSeqID=1)) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=2))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=3))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=9))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=10)))
BEGIN
SELECT 'All'
END
ELSE IF ((#tmpRange < (select ISNULL(Value,0) from #tableA intSeqID=1)) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=2))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=3))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=9))))
BEGIN
SELECT '10'
END
END
How can i simplify this query to compare values. Or is there any other way to pick the values of multiple rows and compare the same with temp variable.
Here is one fairly simple way to do it:
Create and populate sample table (Please save us this step in your future questions)
DECLARE #tableA as table
(
intSeqID int identity(1,1),
Value numeric(5,2)
)
INSERT INTO #tableA VALUES
(779.40),
(357.38),
(256.32),
(NULL)
Declare and populate the variable:
DECLARE #tmpRange numeric(5, 2) = 636
The query:
;WITH CTE AS
(
SELECT TOP 1 intSeqId
FROM #TableA
WHERE #tmpRange < ISNUll(Value, 0)
ORDER BY Value
)
SELECT CASE WHEN intSeqId =
(
SELECT TOP 1 intSeqId
FROM #TableA
ORDER BY ISNUll(Value, 0)
) THEN 'All'
ELSE CAST(intSeqId as varchar(3))
END
FROM CTE
Result: 1.
See a live demo on rextester.
We can try to refactor your query using aggregations. We almost get away with no subquery except for just one, which is needed to distinguish the two conditions.
SELECT
CASE WHEN SUM(CASE WHEN #tmpRange < Value THEN 1 ELSE 0 END) = 4 AND
#tmpRange < (SELECT Value FROM #tableA WHEREA intSeqID = 10)
THEN 'All'
WHEN SUM(CASE WHEN #tmpRange < Value THEN 1 ELSE 0 END) = 4
THEN '10'
ELSE 'NONE' END AS label
FROM #tableA
WHERE intSeqID IN (1, 2, 3, 9)
You want to find the biggest record in Value, who is also smaller than your variable, correct?
--DECLARE #tableA TABLE (intSeqID tinyint, [Value] decimal(5,2))
--INSERT INTO #tableA SELECT 1, 400 UNION SELECT 2, 300 UNION SELECT 3, 200
--DECLARE #tmpRange decimal(5,2) = 250
SELECT TOP 1 *
FROM (
SELECT TOP 1 CONCAT('', intSeqID) AS intSeqID -- Can't UNION int to varchar.
FROM #tableA
WHERE ISNULL([Value], 0) < #tmpRange
ORDER BY intSeqID ASC
UNION
SELECT 'All' AS [?]
) AS T
ORDER BY intSeqID ASC

Need to create new record from beginning when case value matched

I know that if case statement find any first match for that record, it will not check rest of the condition for that record(in my case record 2).
I tried UNION too which is gives me the right result but with some extra records. Any approach would do it for me.
create table #temp (Name varchar(100), ColA int, ColB int, ColC int, ColD int)
insert into #temp (name, ColA,ColB, ColC, ColD)
values ('Name1', 1, null, null, null)
,('Name2', 1, 1 , null, null)
select name,
case
when ColA = 1 then 'some value'
when ColB = 1 then 'Other value'
when ColC = 1 then 'some2 value'
when ColD = 1 then 'some3 value'
end CaseValues
from #temp
select * from #temp
/*when you run this case statement I get only two record. But I need three records for each value matched as below:
Name CaseValues
1 Name1 Some value
2 Name2 some vaule
3 Name2 other value
*/
select name, 'some value'
from from #temp
where ColA = 1
union
select name, 'Other value'
from #temp
where ColB = 1
union
...
Like this?
select name, 'some value' from #temp where colA is not null
union all
select name, 'Other value' from #temp where colB is not null
union all
select name, 'some2 value' from #temp where colC is not null
union all
select name, 'some3 value' from #temp where colD is not null

Check for null and replace the most recent not null value

The Query needs to Check for null value and replace with the most recent not null value.
For example consider the source data provided below .
Query needs to check the null value and found it in second row, now it should replace the null value with recent not null data and the data is"colmin".
Again the Query need to check the null value and Now it found it in third row and then it will update with recent not null data and the data is again "colmin".
Thanks in advance !
Input
source data
Colmin
NULL
NULL
NULL
NULL
columnxy
column99
NULL
NULL
money
NULL
NULL
NULL
start end
NULL
so the output should look like..
output
Ouput data
Colmin
Colmin
Colmin
Colmin
Colmin
Colmin
columnxy
column99
column99
column99
money
money
money
money
start end
start end
What is "most recent" ? I hope you've got some field to sort on. Row number MUST NOT ALWAYS be in right order! Though I'd use orderField which is will be used to determine the row order.
UPDATE myTable
SET a = (
SELECT a
FROM myTable
WHERE a IS NOT NULL
AND orderField > (
SELECT orderField
FROM myTable
WHERE a IS NULL
ORDER BY orderField
LIMIT 1
)
ORDER BY orderField
LIMIT 1
)
WHERE a IS NULL
ORDER BY orderField
something like this should do it ... i hope. it's untested.
what it does:
Find "orderField" for first row with a = null
Find first a value (!= null) AFTER orderField from 1.
Update a value from 1. with value from 2.
It should also work more easy:
UPDATE myTable t1
SET t1.a = (
SELECT t2.a
FROM myTable t2
WHERE t2.a IS NOT NULL
AND t2.orderField > t1.orderField
ORDER BY t2.orderField
LIMIT 1
)
WHERE t1.a IS NULL
Try this:
declare #input table (id bigint not null identity(1,1), OutputData nvarchar(16) null)
insert #input select 'Colmin'
insert #input select NULL
insert #input select NULL
insert #input select NULL
insert #input select NULL
insert #input select 'columnxy'
insert #input select 'column99'
insert #input select NULL
insert #input select NULL
insert #input select 'money'
insert #input select NULL
insert #input select NULL
insert #input select NULL
insert #input select 'start end'
insert #input select NULL
--where a's value is null, replace with a non-null from b
select coalesce(a.OutputData, b.OutputData)
--return all rows from input as a
from #input a
--return all non-null values as b
left outer join
(
select id, OutputData
from #input
where OutputData is not null
) b
--the non-null value should come before the null value (< or <= works equally here)
on b.id <= a.id
--and there shouldn't be a non-null value between b and a's records (i.e. b is the most recent before a)
and not exists (
select top 1 1
from #input c
where c.id between b.id and a.id
and c.id <> b.id
and c.OutputData is not null
)
--display the output in the required order
order by a.id
If your table is a single column, then you will need to either run multiple queries in a loop or use a cursor to iterate through the table, one row at a time. (not efficient.)
If you have some kind of ID column, then you can use a correlated subquery to find the first non-null value. Something like...
Update A
Set TextCol = (SELECT Top 1 TextCol From MyTable B Where B.TextCol IS NOT NULL AND B.IDCol < A.IDCol ORDER BY IDCol DESC)
FROM MyTable A
WHERE TextCol IS NULL

nvarchar column to find the previous date in sql

I have followin table schema
declare #temp table
(
id int identity(1,1) not null,
nod nvarchar(50)
)
in which nod column have following data
insert into #temp select 'N/A'
insert into #temp select 'N/A'
insert into #temp select '5'
insert into #temp select 'N/A'
insert into #temp select '7'
insert into #temp select 'N/A'
insert into #temp select '31'
insert into #temp select '15'
i want that select stament shoud give me result on following basis
if nod value 'N/A' then it should show 'N/A'
or if there any numeric value like 5,15,31 then it should show getdate()-nod date date column
I have tried following but fail to minus the days and also represent 'N/A' when 'N/A' in that nvarchar column
select DATEADD(dd,case nod when 'N/A' then 0 else nod end,GETDATE()) from #temp
sql fiddle is here
The following query would return a VARCHAR(50) column that contains either 'N/A' or now - nod date as varchar.
SELECT
CASE nod
WHEN 'N/A' THEN 'N/A'
ELSE CONVERT(VARCHAR(50),
DATEADD(dd,
-1 * CONVERT(INT, nod),
GETDATE()
)
)
END
FROM #temp

Compare multiple columns, but only those having valid values, and create y/n flag if all are equal

I want to create a Y/N flag, where Y indicates every valid value in every column in a given row is equal, and N otherwise. I need to exclude from consideration any column that contains nulls, blanks, or all zeroes. Suppose:
CREATE TABLE z_test
(ID INT NOT NULL,
D1 VARCHAR(8)NULL,
D2 VARCHAR(8)NULL,
D3 VARCHAR(8)NULL,
D4 VARCHAR(8)NULL,
DFLAG CHAR(1)NULL)
INSERT INTO z_test VALUES (1,NULL,' ','000000','00000000',NULL)
INSERT INTO z_test VALUES (1,'20120101','0000','20120101','00000000',NULL)
INSERT INTO z_test VALUES (2,'20100101','20100101','20100101','20100101',NULL)
INSERT INTO z_test VALUES (2,'00000000','20090101','0','20090101',NULL)
INSERT INTO z_test VALUES (3,'00000000','20090101',NULL,'20120101',NULL)
INSERT INTO z_test VALUES (3,'20100101',' ',NULL,'20100101',NULL)
The desired output (excluding D1 through D4, though I don't want to drop them) is:
ID DFLAG
---------------
1 N
1 Y
2 Y
2 Y
3 N
3 Y
Speed is not a concern as this query will not be run very often but it is on a largish table.
Any pointers or suggestions would be very much appreciated!!
SELECT ID,
CASE
WHEN C = 1 THEN 'Y'
ELSE 'N'
END AS DFLAG
FROM z_test
CROSS APPLY (SELECT COUNT(DISTINCT D) C
FROM (VALUES(D1),
(D2),
(D3),
(D4)) V(D)
WHERE LEN(D) > 0 /*Excludes blanks and NULLs*/
AND D LIKE '%[^0]%'/*Excludes ones with only zero*/) CA
This works:
select case when
(D1 is null OR D2 is null OR LEN(REPLACE(D1,'0',''))=0 OR LEN(REPLACE(D2,'0',''))=0 OR D1=D2)
AND (D1 is null OR D3 is null OR LEN(REPLACE(D1,'0',''))=0 OR LEN(REPLACE(D3,'0',''))=0 OR D1=D3)
AND (D1 is null OR D4 is null OR LEN(REPLACE(D1,'0',''))=0 OR LEN(REPLACE(D4,'0',''))=0 OR D1=D4)
AND (D2 is null OR D3 is null OR LEN(REPLACE(D2,'0',''))=0 OR LEN(REPLACE(D3,'0',''))=0 OR D2=D3)
AND (D2 is null OR D4 is null OR LEN(REPLACE(D2,'0',''))=0 OR LEN(REPLACE(D4,'0',''))=0 OR D2=D4)
AND (D3 is null OR D4 is null OR LEN(REPLACE(D3,'0',''))=0 OR LEN(REPLACE(D4,'0',''))=0 OR D3=D4)
AND (LEN(REPLACE(D1,'0','')) > 0
OR LEN(REPLACE(D2,'0','')) > 0
OR LEN(REPLACE(D3,'0','')) > 0
OR LEN(REPLACE(D4,'0','')) > 0)
THEN 'Y' ELSE 'N' END
from z_test
Here is the link to sqlfiddle.
try this:
DECLARE #z_test table
(ID INT NOT NULL,
D1 VARCHAR(8)NULL,
D2 VARCHAR(8)NULL,
D3 VARCHAR(8)NULL,
D4 VARCHAR(8)NULL,
DFLAG CHAR(1)NULL)
INSERT INTO #z_test VALUES (1,NULL,' ','000000','00000000',NULL)
INSERT INTO #z_test VALUES (1,'20120101','0000','20120101','00000000',NULL)
INSERT INTO #z_test VALUES (2,'20100101','20100101','20100101','20100101',NULL)
INSERT INTO #z_test VALUES (2,'00000000','20090101','0','20090101',NULL)
INSERT INTO #z_test VALUES (3,'00000000','20090101',NULL,'20120101',NULL)
INSERT INTO #z_test VALUES (3,'20100101',' ',NULL,'20100101',NULL)
;WITH Fixed AS
(SELECT --converts columns with all zeros and any spaces to NULL
ID
,NULLIF(NULLIF(D1,''),0) AS D1
,NULLIF(NULLIF(D2,''),0) AS D2
,NULLIF(NULLIF(D3,''),0) AS D3
,NULLIF(NULLIF(D4,''),0) AS D4
FROM #z_test
)
SELECT --final result set
ID,
CASE
WHEN COALESCE(D1,D2,D3,D4) IS NULL THEN 'N' --all columns null
WHEN (D1 IS NULL OR D1=COALESCE(D1,D2,D3,D4)) --all columns either null or the same
AND (D2 IS NULL OR D2=COALESCE(D1,D2,D3,D4))
AND (D3 IS NULL OR D3=COALESCE(D1,D2,D3,D4))
AND (D4 IS NULL OR D4=COALESCE(D1,D2,D3,D4))
THEN 'Y'
ELSE 'N'
END
FROM Fixed
OUTPUT:
ID
----------- ----
1 N
1 Y
2 Y
2 Y
3 N
3 Y
(6 row(s) affected)
You can create a function for this.
create function fnRowValid(#d1 varchar, #d2 varchar...)
returns bit ------ 1 for true and 0 for false
begin
declare table #validvalue (val varchar)
if isdate(d1) = 0 and isdate(d1) = 0 and ...
return 0
if isdate(#d1)
insert into #validvalue (val) values (#d1)
if isdate(#d2)
insert into #validvalue (val) values (#d2)
if isdate(#d3)
insert into #validvalue (val) values (#d3)
...
if exists (select 1 from #validvalue)
if (select count(distinct val) from #validvalue) = 1
return 1
return 0
end
Then you can use this in the update statement...
update z_test
set dflag = dbo.fnRowValid(d1,d2,d3..)
Please don't flame me for this... I didn't test this code obviously. And this is the first solution that popped into my head... not a real elegant but should work. I'm not positive you can use table variables in a function either. Sorry about the ugly solution.
With RnkSource As
(
Select Id, D1, D2, D3, D4, DFlag
, Row_Number() Over ( Order By Id ) As RowNum
From z_test
)
, Source As
(
Select RowNum, Id, 'D1' As Col, D1 As Val
From RnkSource
Union All
Select RowNum, Id, 'D2', D2
From RnkSource
Union All
Select RowNum, Id, 'D3', D3
From RnkSource
Union All
Select RowNum, Id, 'D4', D4
From RnkSource
)
Select Id
, Case When Count(*) = 4 Then 'Y' Else 'N' End As DFLAG
From Source As S
Where Len(Val) > 0
Group By RowNum, Id
SQL Fiddle version