user3046022
user3046022

Reputation: 1

TSQL between with varchar columns problems

I am having trouble with using Between in comparison using varchar columns. When I run this:

SELECT DISTINCT diag_1, Diag_2, Diag_Admit
FROM  Data_Exchange c

WHERE (Diag_1  BETWEEN '29600' and '29606' )

OR (Diag_2 BETWEEN '29600' and '29606')

OR (Diag_Admit between  '29600' and '29606')
------
OR (Diag_1 between '29640' and  '29680')

OR (Diag_2 between '29640' and '29680')

OR (Diag_Admit between '29640' and '29680')

I get the following shows up among the results: 2967

I don't want that. If it does not have 5 digits it should not show up in the results.

How do I fix this?

Thanks.

Upvotes: 0

Views: 604

Answers (2)

Mack
Mack

Reputation: 2552

If all you want to do is limit the length of strings to check to 5 characters then add a where clause for each column:

--Untested(sorry)
SELECT DISTINCT diag_1, Diag_2, Diag_Admit
FROM  Data_Exchange c
WHERE LEN(Diag_1)=5 
AND LEN(Diag_2)=5
AND LEN(Diag_Admit)=5
AND (   Diag_1  BETWEEN '29600' and '29606'
     OR Diag_2 BETWEEN '29600' and '29606'
     OR Diag_Admit between  '29600' and '29606'
     OR Diag_1 between '29640' and  '29680'
     OR Diag_2 between '29640' and '29680'
     OR Diag_Admit between '29640' and '29680')

However: Looking at all those numbers in a varchar column makes me concerned that something else might be going on...

When the column is an alpha type then it is sorted alphabetically so '2967' should be between '29640' and '29680'.

Ideally if the column only contains numbers you should convert the datatype to an appropriate numeric type, but if this is not possible here is a workaround.

Sorted alphabetically the list 1,2,11,12,13 would be shown as 1,11,12,13,2 as can be seen in the following SQL.

--Test data.
DECLARE @alphaSort AS TABLE(col1 VARCHAR(2))
INSERT INTO @alphaSort VALUES('1')
INSERT INTO @alphaSort VALUES('2')
INSERT INTO @alphaSort VALUES('11')
INSERT INTO @alphaSort VALUES('12')
INSERT INTO @alphaSort VALUES('13')
SELECT col1 FROM @alphaSort ORDER BY col1

--Results:
col1
1
11
12
13
2

If you want the BETWEEN statement to work predictably for numbers you must convert the column to a numeric type:

SELECT col1 FROM @alphaSort ORDER BY CONVERT(INT,col1)
--Results
col1
1
2
11
12
13

If you have mixed data in the column then you will need to use the ISNUMERIC function to avoid the following error:

--New test data.
DECLARE @alphaSort AS TABLE(col1 VARCHAR(2))
INSERT INTO @alphaSort VALUES('1')
INSERT INTO @alphaSort VALUES('2')
INSERT INTO @alphaSort VALUES('11')
INSERT INTO @alphaSort VALUES('12')
INSERT INTO @alphaSort VALUES('13')
INSERT INTO @alphaSort VALUES('a')

--WITHOUT ISNUMERIC
SELECT col1 FROM @alphaSort ORDER BY CONVERT(INT,col1)

--Results
Msg 245, Level 16, State 1, Line xx
Conversion failed when converting the nvarchar value 'a' to data type int.

--WITH ISNUMERIC
SELECT col1 FROM @alphaSort WHERE ISNUMERIC(col1) = 1 ORDER BY CONVERT(INT,col1)

--Results
col1
1
2
11
12
13

Upvotes: 1

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117301

If all you want to do is test that the the size of the column is grater then 4 you could so something like

select * from Data_Exchange 
where len(Diag_1) >4 

If not i think you need to add another set of () around your where clause. I think its getting confused

SELECT DISTINCT diag_1, Diag_2, Diag_Admit
FROM  Data_Exchange c
WHERE ((Diag_1  BETWEEN '29600' and '29606' )
   OR (Diag_2 BETWEEN '29600' and '29606')
   OR (Diag_Admit between  '29600' and '29606')
   OR (Diag_1 between '29640' and  '29680')
   OR (Diag_2 between '29640' and '29680')
   OR (Diag_Admit between '29640' and '29680'))

Upvotes: 0

Related Questions