I need to represent the following records
DATA
000200AA
00000200AA
000020BCD
00000020BCD
000020ABC
AS
DATA CNT
200AA 1
20BCD 2
20ABC 2
ANY IDEAS?
USE patindex
select count(test) as cnt,
substring(test, patindex('%[^0]%',test),len(test)) from (
select ('000200AA') as test
union
select '00000200AA' as test
union
select ('000020BCD') as test
union
select ('00000020BCD') as test
union
select ('000020ABC') as test
)ty
group by substring(test, patindex('%[^0]%',test),len(test))
How about a nice recursive user-defined function?
CREATE FUNCTION dbo.StripLeadingZeros (
#input varchar(MAX)
) RETURNS varchar(MAX)
BEGIN
IF LEN(#input) = 0
RETURN #input
IF SUBSTRING(#input, 1, 1) = '0'
RETURN dbo.StripLeadingZeros(SUBSTRING(#input, 2, LEN(#input) - 1))
RETURN #input
END
GO
Then:
SELECT dbo.StripLeadingZeros(DATA) DATA, COUNT(DATA) CNT
FROM YourTable GROUP BY dbo.StripLeadingZeros(DATA)
DECLARE #String VARCHAR(32) = N'000200AA'
SELECT SUBSTRING ( #String ,CHARINDEX(N'2', #String),LEN(#String))
Depending on the what you need to get the values this code may differ:
Assuming a simple right 5 chars as Barry suggested, you can use RIGHT(data, 5) and GROUP BY and COUNT to get your results
http://sqlfiddle.com/#!3/19ecd/2
take a look at the STUFF function
It inserts data into a string on a range
You can do this query:
SELECT RIGHT([DATA],LEN[DATA])-PATINDEX('%[1-9]%',[DATA])+1) [DATA], COUNT(*) CNT
FROM YourTable
GROUP BY RIGHT([DATA],LEN[DATA])-PATINDEX('%[1-9]%',[DATA])+1)
Related
Trying to write a query for printing each character of a string separately. I have tried the following
select substring('sas',1,1)
union all
select substring('sas',2,1)
union all
select substring('sas',3,1)
But I would have to run union all for each character. Any better approach to this?
Sandbox: http://sqlfiddle.com/#!9/9eecb/123683
DECLARE #data VARCHAR(100) = 'October 11, 2017'
;WITH CTE AS
(
SELECT STUFF(#data,1,1,'') TXT, LEFT(#data,1) Col1
UNION ALL
SELECT STUFF(TXT,1,1,'') TXT, LEFT(TXT,1) Col1 FROM CTE
WHERE LEN(TXT) > 0
)
select Col1, ISNUMERIC(Col1) from CTE
You can try this as well
DECLARE #data VARCHAR(100) = 'TEST'
Declare #cnt int = len(#data)
Declare #i int =1
While (#i <= #cnt)
BEGIN
PRint SUBSTRING(#data,#i,1)
set #i=#i+1
END
I really don't like the use of an rCTE for tasks like this, that are iterative and slow (far slower than a Tally, especially when more than a few rows). You could use a Tally and do this far faster. As a TVF, this would like like this:
CREATE FUNCTION dbo.GetChars (#String varchar(8000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM(VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(#String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4)
SELECT SUBSTRING(#String, T.I, 1) AS C, T.I
FROM Tally T;
GO
db<>fiddle
Note, this will not work on SQL Server 2005.
Consider the following table:
MyValue
--------------------
123
122_DELETED
45670
42425
43_NO_VIEW
4365463_CORRUPT
53
4335_NO_VIEW_ALLOWED
I'm trying to get only the numbers returned. In other words: string everything after the first underscore (_):
select
left(MyValue, charindex(('_', MyValue)-1)
from
DB.Table
However, this returns the error Invalid length parameter passed to the LEFT or SUBSTRING function. I believe this is because the value is NULL in case the current value has no underscore (for instance, 123).
How can I account for this exception? Any help is greatly appreciated.
I am on SQL Server 2008.
try this!
select myval,case when myval like '%[_]%' then
substring(myval,1,patindex('%[_]%',myval)-1) else myval end from t
##DEMO USING PATINDEX
##DEMO USING CHARINDEX
select SUBSTRING(MyValue,CHARINDEX('_',MyValue)+1,LEN(MyValue)) from DB.Table
try this
select
case when MyValue is null then '' --if null return empty string
when charindex('_', MyValue) > 0 then
left(MyValue, charindex('_', MyValue)-1)
else
MyValue --Return the field value if an underscore is not present
end as Result
from
DB.Table
Try out this one:
declare #st varchar(20)
set #st ='4365463_CORRU'
select #st, SUBSTRING(#st,CHARINDEX('_',#st)-LEN(#st),LEN(#st))
Check this .
declare #t table (myvalue varchar(50))
insert into #t
values ( '123'),('122_DELETED'),('45670'),('42425'),('43_NO_VIEW'),('4365463_CORRUPT'),('53'),('4335_NO_VIEW_ALLOWED')
select * from #t
;With cte as
(
select CHARINDEX( '_', myvalue)+1 d , myvalue from #t
)
select SUBSTRING(myvalue,d,LEN(myvalue) ) from cte
Simplified scenario, I have a table with the following fields/values:
ID value
1 '12345'
2 '1234'
3 '123'
4 '12'
5 '1'
I want to find the record that is the closest to A='1230' and it should correspond to ID=3.
The only implementation I have in mind now is basic... Use a loop to iterate through A substring and do the comparison.
Is there a better way to solve this?
Will appreciate your help
Try this :-
Declare #valueToSearch int
Set #valueToSearch =1230
;WITH cte
AS
(
SELECT ID,RANK() OVER(ORDER BY ABS(value-#valueToSearch)) AS num FROM Sample
)
SELECT ID FROM cte
WHERE num=(SELECT MIN(num) FROM cte
This will give 2 as the result
Sql Fiddle
declare #q varchar(5)
select #q = '1230'
select top 1 number, substring(source.value, 1, number)
from master.dbo.spt_values, source
where type='p'
and number<=len(source.value)
and substring(source.value, 1, number) = substring(#q, 1, number)
order by number desc
Or using like...
select top 1 * from #source s
where #q like value +'%'
order by len(value) desc
I have a very interesting problem. I have an SSRS report with a multiple select drop down.
The drop down allows to select more than one value, or all values.
All values is not the problem.
The problem is 1 or the combination of more than 1 option
When I select in the drop down 'AAA' it should return 3 values: 'AAA','AAA 1','AAA 2'
Right now is only returning 1 value.
QUESTION:
How can make the IN statement work like a LIKE?
The Drop down select
SELECT '(All)' AS team, '(All)' AS Descr
UNION ALL
SELECT 'AAA' , 'AAA'
UNION ALL
SELECT 'BBB' , 'BBB'
Table Mytable
ColumnA Varchar(5)
Values for ColumnA
'AAA'
'AAA 1'
'AAA 2'
'BBB'
'BBB 1'
'BBB 2'
SELECT * FROM Mytable
WHERE ColumnA IN (SELECT * FROM SplitListString(#Team, ',')))
Split function
CREATE FUNCTION [dbo].[SplitListString]
(#InputString NVARCHAR(max), #SplitChar CHAR(1))
RETURNS #ValuesList TABLE
(
param NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #ListValue NVARCHAR(max)
DECLARE #TmpString NVARCHAR(max)
DECLARE #PosSeparator INT
DECLARE #EndValues BIT
SET #TmpString = LTRIM(RTRIM(#InputString));
SET #EndValues = 0
WHILE (#EndValues = 0) BEGIN
SET #PosSeparator = CHARINDEX(#SplitChar, #TmpString)
IF (#PosSeparator) > 1 BEGIN
SELECT #ListValue = LTRIM(RTRIM(SUBSTRING(#TmpString, 1, #PosSeparator -1 )))
END
ELSE BEGIN
SELECT #ListValue = LTRIM(RTRIM(#TmpString))
SET #EndValues = 1
END
IF LEN(#ListValue) > 0 BEGIN
INSERT INTO #ValuesList
SELECT #ListValue
END
SET #TmpString = LTRIM(RTRIM(SUBSTRING(#TmpString, #PosSeparator + 1, LEN(#TmpString) - #PosSeparator)))
END
RETURN
END
You can't. But, you can make the like work like the like:
select *
from mytable t join
SplitListString(#Team, ',') s
on t.ColumnA like '%'+s.param+'%'
That is, move the split list to an explicit join. Replace with the actual column name returned by the function, and use the like function.
Or, if you prefer:
select *
from mytable t cross join
SplitListString(#Team, ',') s
where t.ColumnA like '%'+s.param+'%'
The two versions are equivalent and should produce the same execution plan.
Better approach would be to have a TeamsTable (teamID, teamName, ...) and teamMembersTable (teamMemberID, teamID, teamMemberDetails, ...).
Then you an build your dropdown list as
SELECT ... FROM TeamsTable ...;
and
SELECT ... FROM teamMembersTable WHERE teamID IN (valueFromYourDropDown);
Or you can just store your teamID or teamName (or both) in your (equivalent of) teamMembersTable
You're not going to get IN to work the same as LIKE without a lot of work. You could do something like this though (and it would be nice to see some of your actual data though so we could give better solutions):
SELECT *
FROM table
WHERE LEFT(field,3) IN #Parameter
If you'd like better performance, create a code field on your table and update it like this:
UPDATE table
SET codeField = LEFT(field,3)
Then just add an index on that field and run this query to get your results:
SELECT *
FROM table
WHERE codeField IN #Parameter
I want to write an SQL statement like below:
select * from tbl where col like ('ABC%','XYZ%','PQR%');
I know it can be done using OR. But I want to know is there any better solution.
This is a good use of a temporary table.
CREATE TEMPORARY TABLE patterns (
pattern VARCHAR(20)
);
INSERT INTO patterns VALUES ('ABC%'), ('XYZ%'), ('PQR%');
SELECT t.* FROM tbl t JOIN patterns p ON (t.col LIKE p.pattern);
In the example patterns, there's no way col could match more than one pattern, so you can be sure you'll see each row of tbl at most once in the result. But if your patterns are such that col could match more than one, you should use the DISTINCT query modifier.
SELECT DISTINCT t.* FROM tbl t JOIN patterns p ON (t.col LIKE p.pattern);
Oracle 10g has functions that allow the use of POSIX-compliant regular expressions in SQL:
REGEXP_LIKE
REGEXP_REPLACE
REGEXP_INSTR
REGEXP_SUBSTR
See the Oracle Database SQL Reference for syntax details on this functions.
Take a look at Regular expressions in Perl with examples.
Code :
select * from tbl where regexp_like(col, '^(ABC|XYZ|PQR)');
Here is an alternative way:
select * from tbl where col like 'ABC%'
union
select * from tbl where col like 'XYZ%'
union
select * from tbl where col like 'PQR%';
Here is the test code to verify:
create table tbl (col varchar(255));
insert into tbl (col) values ('ABCDEFG'), ('HIJKLMNO'), ('PQRSTUVW'), ('XYZ');
select * from tbl where col like 'ABC%'
union
select * from tbl where col like 'XYZ%'
union
select * from tbl where col like 'PQR%';
+----------+
| col |
+----------+
| ABCDEFG |
| XYZ |
| PQRSTUVW |
+----------+
3 rows in set (0.00 sec)
select * from tbl where col like 'ABC%'
or col like 'XYZ%'
or col like 'PQR%';
This works in toad and powerbuilder. Don't know about the rest
This might help:
select * from tbl where col like '[ABC-XYZ-PQR]%'
I've used this in SQL Server 2005 and it worked.
I also had the same requirement where I didn't have choice to pass like operator multiple times by either doing an OR or writing union query.
This worked for me in Oracle 11g:
REGEXP_LIKE (column, 'ABC.*|XYZ.*|PQR.*');
Even u can try this
Function
CREATE FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20))
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
Query
select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
If your parameter value is not fixed or your value can be null based on business you can try the following approach.
DECLARE #DrugClassstring VARCHAR(MAX);
SET #DrugClassstring = 'C3,C2'; -- You can pass null also
---------------------------------------------
IF #DrugClassstring IS NULL
SET #DrugClassstring = 'C3,C2,C4,C5,RX,OT'; -- If null you can set your all conditional case that will return for all
SELECT dn.drugclass_FK , dn.cdrugname
FROM drugname AS dn
INNER JOIN dbo.SplitString(#DrugClassstring, ',') class ON dn.drugclass_FK = class.[Name] -- SplitString is a a function
SplitString function
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
ALTER FUNCTION [dbo].[SplitString](#stringToSplit VARCHAR(MAX),
#delimeter CHAR(1) = ',')
RETURNS #returnList TABLE([Name] [NVARCHAR](500))
AS
BEGIN
--It's use in report sql, before any change concern to everyone
DECLARE #name NVARCHAR(255);
DECLARE #pos INT;
WHILE CHARINDEX(#delimeter, #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX(#delimeter, #stringToSplit);
SELECT #name = SUBSTRING(#stringToSplit, 1, #pos-1);
INSERT INTO #returnList
SELECT #name;
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+1, LEN(#stringToSplit)-#pos);
END;
INSERT INTO #returnList
SELECT #stringToSplit;
RETURN;
END;
I had to add all to Asaph's answer to make it work.
select * from tbl where col like 'ABC%'
union all
select * from tbl where col like 'XYZ%'
union all
select * from tbl where col like 'PQR%';
SELECT *
From tbl
WHERE col
LIKE '[0-9,a-z]%';
simply use this condition of like in sql and you will get your desired answer