How to only get non numeric part of column out [duplicate] - sql

This question already has answers here:
How to strip all non-alphabetic characters from string in SQL Server?
(21 answers)
Closed 9 years ago.
I have a column called TCODE which has value like 5T, 6545H,25 and S4444.
Now I want only 3 rows out of the 4 rows returned and only the following non numeric bits of those columns T,H or S. Table name is CODES .
Pseudo code
Select TCODE from CODES where I strip out numeric part of those columns where a mix of numeric and non numeric exist.
Expected Results
TCODE
T
H
S
How can I do this ?

In SQL Server, you can possibly use PATINDEX:
SELECT SUBSTRING(TCODE,PATINDEX('%[^0-9]%', TCODE),1)
FROM CODES
WHERE PATINDEX('%[^0-9]%',TCODE) > 0

The way that comes to my mind is the rather brutish:
select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(tcode, '0', ''),
'1', 0),
'2', 0),
'3', 0),
'4', 0),
'5', 0),
'6', 0),
'7', 0),
'8', 0),
'9', 0) as theletters
. . .
You can put this in a subquery, and then select where theletters <> '' for the filtering.

One alternative:
with cte as
(select 0 n, replace(tcode,'0','') tcode from codes
union all
select n+1 n, replace(tcode,convert(varchar,n+1),'') tcode
from cte
where n<9)
select tcode from cte
where n=9
(SQLFiddle here)

You can create a function like this
CREATE FUNCTION RemoveDigits(#strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
WHILE PATINDEX('%[0-9]%', #strText) > 0
BEGIN
SET #strText = STUFF(#strText, PATINDEX('%[0-9]%', #strText), 1, '')
END
RETURN #strText
END
GO
And then use it
SELECT dbo.RemoveDigits(TCODE) TCODE
FROM CODES
WHERE PATINDEX('%[^0-9]%', TCODE) > 0
Output:
| TCODE |
---------
| T |
| H |
| S |
SQLFiddle

Related

How to find values that contains only 0's and any other digit for example 000000001 or 0000010001 or 010101 or 0002 or 02020 or 0090 etc.?

I want to find 'default type values' in SQL that is entered when something like an ID number of company registration number is entered. Some of the values I see is a combination of 0's and another digit from 1-9. Examples I have seen is 00000001, 0000100, 000000002, 000001111, 0000090009, etc. The values vary in length also. Is there a way to find these values without hard coding? The value should contain at least one 0 and one or more of any other digit.
You want all strings that consist of only zero and one other digit. I.e. you want to find '0101', but not '0102'.
In order to do this, remove all zeros first. From the remaining string remove all digits equaling to its first character. This will result in an empty string or a string consisting of additional digits or characters. Only select those resulting in an empty string.
select *
from mytable
where replace(replace(value, '0', ''), substring(replace(value, '0', ''), 1, 1), '') = '';
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=c307bbbf21ceeae619a966e995c3a567
You can use ISNUMERIC() function
SELECT ISNUMERIC(0000004);
This will return 1
SELECT ISNUMERIC('A');
This will return 0
So if you want to select all columns that are numeric only you can use this logic:
select *
from test
where ISNUMERIC(colA) = 1
Here is a small demo
Or you can use TRY_CAST() function:
select *
from test
where try_cast(colA as int) is not null
Alternative solution:
SELECT value
FROM mytable
CROSS JOIN (
SELECT '1' AS num
UNION ALL
SELECT '2'
UNION ALL
SELECT '3'
UNION ALL
SELECT '4'
UNION ALL
SELECT '5'
UNION ALL
SELECT '6'
UNION ALL
SELECT '7'
UNION ALL
SELECT '8'
UNION ALL
SELECT '9'
) n
WHERE REPLACE(REPLACE(value, '0', ''), num, '') = ''
AND REPLACE(value, '0', '') <> ''
AND value LIKE '%0%'

sql query to sum data based on criteria

I have my table data sums as follows
---------------------
Building | Area m2
---------------------
|Dante 12 | 10
|Dante 10 | 5
|Dante 9 | 2
|Crandley | 20
|Bence | 30
I want to sum Building Area but buildings like '%dante%' I want to combine into sum "Dante" like below:
-------------------
Building | Area m2
-------------------
Dante | 17
Crandley | 20
Bence | 30
Group by with case will do the trick for sample data given,like of this type can use index as well
Select
case when building like 'dante%' then 'Dante' else building end,
sum([area m2])
from
table
group by
case when building like 'dante%' then 'Dante' else building end
if there are numbers for other columns,you can strip out the numbers first and do the rest of stuff like below
;with cte
as
(select REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (building, '0', ''),
'1', ''),
'2', ''),
'3', ''),
'4', ''),
'5', ''),
'6', ''),
'7', ''),
'8', ''),
'9', '') as bulding,aream2
from #temp
)
select building,sum(aream2)
from
cte
group by
building
References:
Remove numbers found in string column
Works only if numeric value is to be removed
Numeric value is to be replaced (Nested replace function can go upto 32 level deep) and group by column.
SELECT x.Building, SUM(x.AreaM2) AS [Area m2]
FROM (
SELECT
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE (Building, '0', '')
,'1', '')
,'2', '')
,'3', '')
,'4', '')
,'5', '')
,'6', '')
,'7', '')
,'8', '')
,'9', '') [Building], AreaM2 FROM Buildings) AS x
GROUP BY x.Building

Why is one of the queries returning no rows?

I have 2 queries like this:
Query #1:
SELECT *
FROM dbo.Products
WHERE CAST(ID AS VARCHAR) IN ('6', '8', '9', '10', '12', '14', '110', '106')
Query #2:
SELECT *
FROM dbo.Products
WHERE CAST(ID AS VARCHAR) IN (SELECT ('6'', ''8'', ''9'', ''10'', ''12'', ''14'', ''110'', ''106'))
Why does the second query return no rows? When 1st query is returning some rows.
You have way too many single quotes in your query #2...
Also: if ID is a numeric column - why not just use
SELECT *
FROM dbo.Products
WHERE ID IN (6, 8, 9, 10, 12, 14, 110, 106)
Much easier, not unnecessary CAST involved .....
Also: if you ever really do need a CAST - I would recommend to always define a length for your VARCHAR ! Otherwise, you might end up with truncated strings....
So use: CAST(ID AS VARCHAR(100)) instead of just CAST(ID AS VARCHAR)
The second query considers the values as a single string
You have to use '' (single quotes) to seperate character values when used in a IN clause
The second query is equivalent to this:
SELECT *
FROM dbo.Products
WHERE CAST(ID AS VARCHAR) IN ('6'', ''8'', ''9'', ''10'', ''12'', ''14'', ''110'', ''106')
or even this:
SELECT *
FROM dbo.Products
WHERE CAST(ID AS VARCHAR) = '6'', ''8'', ''9'', ''10'', ''12'', ''14'', ''110'', ''106'
So, it returns no rows because you have no row with the ID 6', '8', '9', '10', '12', '14', '110', '106
Why does the second query return no rows? When 1st query is returning
some rows.
Because the values returned by the SELECT statement in the IN predicate in the second query returns only one string value which is:
6','8','9','10','12','14','110','106
So you will end up comparing the casted int ID value with only one string value 6','8','9','10','12','14','110','106' so your query sill be evaluated like so
SELECT *
FROM dbo.Products
WHERE CAST(ID AS VARCHAR) = ''6','8','9','10','12','14','110','106'';
But there are distinct string values inside the IN clause in the first query:
6 8 9 10 12 14 110 106
However, you didn't need to cast it to varchar at all:
SELECT *
FROM dbo.Products
WHERE ID IN (6, 8, 9, 10, 12, 14, 110, 106)

How to select only numeric values

Table1
id
01
wire
02
steve
ram123
03
....
from the table1 i want to select only numeric values,
It should not display alphanumeric values like (ram123)
Expected Output
01
02
03
....
How to make a query for this condition
Try ISNUMERIC
SELECT *
FROM Table1
WHERE ISNUMERIC([ID]) = 1
SQLFiddle Demo
SELECT * FROM #Table
WHERE Col NOT LIKE '%[^0-9]%'
Just want to note that IsNumeric() has some limitations. For example all of the below will return 1.
SELECT ISNUMERIC(' - ')
SELECT ISNUMERIC(' , ')
SELECT ISNUMERIC('$')
SELECT ISNUMERIC('10.5e-1')
SELECT ISNUMERIC('$12.09')
So if you only looking to select numbers ONLY, then something like this could work:
create function [dbo].[IsNumbersOnly](#strSrc as varchar(255))
returns tinyint
as
begin
return isnumeric(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
#strSrc, '\', 'x'), '-', 'x'), ',', 'x'), '+', 'x'), '$', 'x'), '.', 'x'), 'e', 'x'), 'E', 'x'),
char(9), 'x'), char(0), 'x'))
end
SELECT column1 FROM table where ISNUMERIC(column1) = 1
You can use translate and replace function together. first translate the numbers to 0 then replace them with null and return only null values can solve the problem.
select column from table where replace(translate(column,'0123456789','0000000000'),'0','') is null
I tried the code above (ISNUMERIC()) and it somehow doesn't work in Oracle SQL.
But I found a working solution for Oracle SQL:
SELECT column1
FROM Table
WHERE regexp_like( column1, '^[[:digit:]]*$');
From: https://community.oracle.com/thread/2394572

sql query complex

I have table where in a table called test which have 4 fields.one field named as listing, I have 1,2,3,4,5,6 multiple values separated by comma, I need to check whether in that table and in that particular field an id say 4 is there or not.. by a sql query.
You database design is wrong, that's why you have problems querying the data. You should have the values in a separate table, so that teach value is in it's own field. Then it would be easy to find the records:
select t.testId
from test t
inner join listing l on l.testId = t.testId
where l.id = 4
Now you have to use some ugly string comparison to find the records:
select testId
from test
where ','+listing+',' like '%,4,%'
You can try
SELECT *
FROM YourTable
WHERE REPLACE(Col, ' ', '') LIKE '4,%' --Starts with
OR REPLACE(Col, ' ', '') LIKE '%,4' --Ends with
OR REPLACE(Col, ' ', '') LIKE '%,4,%' --Contains
OR REPLACE(Col, ' ', '') = '4' --Equals
Just as a matter of interest, have a look at this
DECLARE #delimiter NVARCHAR(5),
#Val INT
SELECT #Val = 40
SELECT #delimiter = ','
DECLARE #YourTable TABLE(
ID INT,
Vals VARCHAR(50)
)
INSERT INTO #YourTable (ID,Vals) SELECT 1, '1,2,3,4,5,6,7,8'
DECLARE #TempTable TABLE(
ID INT,
Vals XML
)
INSERT INTO #TempTable
SELECT ID,
CAST('<d>' + REPLACE(Vals, #delimiter, '</d><d>') + '</d>' AS XML)
FROM #YourTable
SELECT *
FROM #TempTable tt
WHERE EXISTS(
SELECT T.split.value('.', 'nvarchar(max)') AS data
FROM tt.Vals.nodes('/d') T(split)
WHERE T.split.value('.', 'nvarchar(max)') = #Val
)
The common approach is to parse the list into a table variable or table-valued function, then either join against the table, or use an EXISTS sub-query.
There are lots of examples on how to do this:
http://www.bing.com/search?setmkt=en-US&q=SQL+parse+list+into+table
You could use an instring function in the where clause and in the select clause:
Oracle:
select substr(column, instr(column, '1', 1), 1)
where instr(column, '1', 1) > 0
works if you want a single value. Alternatively you can use a combination of case or decode statements to create a single column for each possible value:
select
decode(instr(column, '1', 1), 0, substr(column, instr(column, '1', 1), 1), null) c1,
decode(instr(column, '2', 1), 0, substr(column, instr(column, '2', 1), 1), null) c2,
decode(instr(column, '3', 1), 0, substr(column, instr(column, '3', 1), 1), null) c3
The beauty of this approach for such a poorly normalised set of data is you can save this as a view and then run SQL on that, so if you save the above you could use:
select c1, c2 from view where c1 is not null or c2 is not null
NB. In other dbms you might have to use different syntax, possibly the case rather decode statement
If you need to find 4 and only 4 (ie not 14 or 24 or 40 etc) you should use
SELECT * FROM foo WHERE col LIKE '%, 4,%'
or
SELECT * FROM foo WHERE col LIKE '%,4,%'
if there are no spaces between the commas and numbers
How about this?
Select * From Foo Where Col like '%4%'