I am a beginner with regex query therefore I want to ask you how to convert this regex query in Oracle to SQL Server?
select *
from Sales
where regexp_like(productname,'^[A-Z]{3}[0-9]+$')
I convert it to this query:
select *
from Sales
where substr(productname, 1, 3) in ([A-Z])
Is that correct?
Thankyou.
You can use the following query:
SELECT *
FROM Sales
WHERE LEFT(productname, 3) LIKE '[A-Z][A-Z][A-Z]' -- three chars ([A-Z]{3})
AND NOT RIGHT(productname, LEN(productname) - 3) LIKE '%[^0-9]%' -- only numbers after the first three chars
AND NOT LEN(RIGHT(productname, LEN(productname) - 3)) = 0 -- at least one number
demo on dbfiddle.uk
Based on regexp '^[A-Z]{3}[0-9]+$':
-- exactly 3 letters
-- at least one trailing digits
You could use TRIM:
SELECT *
FROM Sales
WHERE productname LIKE '[A-Z][A-Z][A-Z][0-9]%'
AND TRIM( '0123456789' FROM productname) LIKE '[A-Z][A-Z][A-Z]';
-- warning! expression is not SARGable
db<>fiddle demo
Think the most simple would be to use
WHERE
SUBSTRING(<column>, 1, 1) IN('A', 'B', 'C')
AND
SUBSTRING(<column>, 2, 1) IN('A', 'B', 'C')
AND
SUBSTRING(<column>, 2, 1) IN('A', 'B', 'C')
AND
TRY_CONVERT(
INT
, SUBSTRING(<column>, 4, LEN(<column>))
) <> 0
as you don't really need regex to do this.
see demo
Related
I need a query or function to count the 0's between 1's in a string.
For example:
String1 = '10101101' -> Result=3
String2 = '11111001101' -> Result=1
String3 = '01111111111' -> Result=1
I only need to search for 101 pattern or 01 pattern if its at the beginning of the string.
You may try to decompose the input strings using SUBTRING() and a number table:
SELECT
String, COUNT(*) AS [101Count]
FROM (
SELECT
v.String,
SUBSTRING(v.String, t.No - 1, 1) AS PreviousChar,
SUBSTRING(v.String, t.No, 1) AS CurrentChar,
SUBSTRING(v.String, t.No + 1, 1) AS NextChar
FROM (VALUES
('10101101'),
('11111001101'),
('01111111111')
) v (String)
CROSS APPLY (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) t (No)
) cte
WHERE
CASE WHEN PreviousChar = '' THEN '1' ELSE PreviousChar END = '1' AND
CurrentChar = '0' AND
NextChar = '1'
GROUP BY String
Result:
String 101Count
10101101 3
11111001101 1
01111111111 1
Notes:
The table with alias v is the source table, the table with alias t is the number table. If the input strings have more than 10 characters, use an appropriate number (tally) table.
-- This converts "111101101010111" in "01101010" and "011101000" in "01110"
regexp_replace(field, '^1*(.*)1*0*$', '\1')
-- This converts "01101010" in "0000"
regexp_replace(field, '1', '')
-- This counts the string length, returning 4 for '0000':
LENGTH(field)
-- Put all together:
LENGTH(
regexp_replace(
regexp_replace(field, '^1*(.*)1*0*$', '\1')
, '1', '')
)
Different or more complicated cases require a modification of the regular expression.
Update
For "zeros between 1s" I see now you mean "101" sequences. This is more complicated because of the possibility of having "10101". Suppose you want to count this as 2:
replace 101 with 11011. Now 10101 will become either 1101101 or 1101111011. In either case, you have the "101" sequence well apart and still only have two of them.
replace all 101s with 'X'. You now have 1X11X1
replace [01] with the empty string. You now have XX.
use LENGTH to count the X's.
Any extra special sequence like "01" at the beginning you can convert as first thing with "X1" ("10" at the end would become "1X"), which will then neatly fold back in the above workflow.
By using the LIKE operator with % you can decide how to search a specific string. In this SQL query I am saying that I want every record that starts as 101 or 01.
SELECT ColumnsYouWant FROM TableYouWant
WHERE ColumnYouWant LIKE '101%' OR '01%';
You can simple COUNT the ColumnYouWant, like this:
SELECT COUNT(ColumnYouWant) FROM TableYouWant
WHERE ColumnYouWant LIKE '101%' OR '01%';
Or you can use a method of your backend language to count the results that the first query returns. This count method will depend on the language you are working with.
SQL Documentation for LIKE: https://www.w3schools.com/sql/sql_like.asp
SQL Documentation for COUNT; https://www.w3schools.com/sql/sql_count_avg_sum.asp
The other solutions do not account for all of the characters (max of 11, of the examples shown)
Data
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1, '10101101'),
(2, '11111001101'),
(3, '01111111111')) V(id, string);
Query
;with
split_cte as (
select id, n, substring(t.string, v.n, 1) subchar
from #tTEST t
cross apply (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
(11),(12),(13),(14),(15),(16),(17),(18),(19),(20)) v(n)
where v.n<=len(t.string)),
lead_lag_cte as (
select id, n, lead(subchar, 1, 9) over (partition by id order by n) lead_c, subchar,
lag(subchar, 1, 9) over (partition by id order by n) lag_c
from split_cte)
select id, sum(case when (lead_c=1 and lag_c=9) then 1 else
case when (lead_c=1 and lag_c=1) then 1 else 0 end end) zero_count
from lead_lag_cte
where subchar=0
group by id;
Results
id zero_count
1 3
2 1
3 1
Another way, perhasp quicker:
DECLARE #T TABLE (ID INT, STRING VARCHAR(32));
INSERT INTO #T
VALUES (1, '10101101'),
(2, '11111001101'),
(3, '01111111111');
SELECT *, LEN(STRING) - LEN(REPLACE(STRING, '0', '')) AS NUMBER_OF_ZERO
FROM #T
Result:
ID STRING NUMBER_OF_ZERO
----------- -------------------------------- --------------
1 10101101 3
2 11111001101 3
3 01111111111 1
select (len(replace('1'+x, '101', '11011')) - len(replace(replace('1'+x, '101', '11011'), '101', '')))/3
from
(
values
('10101101'),
('11111001101'),
('01111111111'),
('01010101010101010101')
) v(x);
I'm using SQL Server 2017 and I would like to ask if it's possible to use the LIKE like operator as follows:
LIKE '%Ticket [8-14]%'
Is this correct or the numbers greater than 9 (10,11, etc etc) will be identified as 1 and 0, 1 and 1, 1 and 2 etc etc.
If this way doesn't work, what can i do to select all the data that contain strings like 'Ticket 10', 'Ticket11' and so on..?
Thank you for your time
As far as I know, no. However, You can do something like:
WITH Demo AS
(
SELECT * FROM (VALUES
('Ticket 1'),
('Ticket 7'),
('Ticket 8'),
('Ticket 10'),
('Ticket 12'),
('Ticket 15')
) T(X)
)
SELECT *
FROM Demo
WHERE X LIKE '%Ticket [8-9]%' OR X LIKE '%Ticket 1[0-4]%'
Also, consider normalization - create TicketNumber column if you need to query over this value. It's much easier to concatenate Ticket and number than parse string. TicketNumber could also be easily indexed if needed.
There is also more clever idea to parse numbers:
WITH Demo AS
(
SELECT * FROM (VALUES
('Ticket 1'),
('Ticket 7'),
('My Ticket 8A'),
('Ticket 10'),
('Some Ticket 12'),
('Ticket 15 other text'),
('Ticket 135 and more')
) T(X)
)
SELECT *, CAST(CASE WHEN PATINDEX('%Ticket [0-9][0-9][0-9]%',X)!=0 THEN SUBSTRING(X, PATINDEX('%Ticket [0-9][0-9][0-9]%',X)+7, 3)
WHEN PATINDEX('%Ticket [0-9][0-9]%',X)!=0 THEN SUBSTRING(X, PATINDEX('%Ticket [0-9][0-9]%',X)+7, 2)
WHEN PATINDEX('%Ticket [0-9]%',X)!=0 THEN SUBSTRING(X, PATINDEX('%Ticket [0-9]%',X)+7, 1)
END AS int) Number
FROM Demo
Column number should now contain simple int value - ready to compare and take part in calculations.
'%Ticket [8-14]%'
The brackets are used to specify a single character, that's usually specified as a lower and upper range like "[0-9]" or "[a-z]".
Your string would match:
"Ticket 1" through "Ticket 8". The 4 would be ignored because it's already handled by the 8-1 range.
It would not match "Ticket 0" or "Ticket 9" or "Ticket 10".
A slightly different approach to Pawel's, but a very similar idea:
SELECT *
FROM YourTable YT
CROSS APPLY(VALUES('8'),('9'),('10'),('11'),('12'),('13'),('14')) V(TN)
WHERE YT.YourColumn LIKE '%Ticket ' + V.TN + '%';
If you're using this as a Stored Procedure, you could use a table-value paramter to hold the data instead. Something like:
CREATE TYPE numbers AS table (Number int);
GO
CREATE PROC YourProc #TicketNumbers numbers READONLY AS
SELECT *
FROM YourTable YT
CROSS JOIN #TicketNumbers TN
WHERE YT.YourColumn LIKE 'Ticket ' + CONVERT(varchar(3),TN.Number) + '%';
GO
Well I had asked the same question for jquery on here, Now my question is same with SQL Server Query :) But this time this is not comma separated, this is separate row in Database like
I have separated rows having float numbers.
Name
K1.1
K1.10
K1.2
K3.1
K3.14
K3.5
and I want to sort this float numbers like,
Name
K1.1
K1.2
K1.10
K3.1
K3.5
K3.14
actually in my case, the numbers which are after decimals will consider as a natural numbers, so 1.2 will consider as '2' and 1.10 will consider as '10' thats why 1.2 will come first than 1.10.
You can remove 'K' because it is almost common and suggestion or example would be great for me, thanks.
You can use PARSENAME (which is more of a hack) or String functions like CHARINDEX , STUFF, LEFT etc to achieve this.
Input data
;WITH CTE AS
(
SELECT 'K1.1' Name
UNION ALL SELECT 'K1.10'
UNION ALL SELECT 'K1.2'
UNION ALL SELECT 'K3.1'
UNION ALL SELECT 'K3.14'
UNION ALL SELECT 'K3.5'
)
Using PARSENAME
SELECT Name,PARSENAME(REPLACE(Name,'K',''),2),PARSENAME(REPLACE(Name,'K',''),1)
FROM CTE
ORDER BY CONVERT(INT,PARSENAME(REPLACE(Name,'K',''),2)),
CONVERT(INT,PARSENAME(REPLACE(Name,'K',''),1))
Using String Functions
SELECT Name,LEFT(Name,CHARINDEX('.',Name) - 1), STUFF(Name,1,CHARINDEX('.',Name),'')
FROM CTE
ORDER BY CONVERT(INT,REPLACE((LEFT(Name,CHARINDEX('.',Name) - 1)),'K','')),
CONVERT(INT,STUFF(Name,1,CHARINDEX('.',Name),''))
Output
K1.1 K1 1
K1.2 K1 2
K1.10 K1 10
K3.1 K3 1
K3.5 K3 5
K3.14 K3 14
This works if there is always one char before the first number and the number is not higher than 9:
SELECT name
FROM YourTable
ORDER BY CAST(SUBSTRING(name,2,1) AS INT), --Get the number before dot
CAST(RIGHT(name,LEN(name)-CHARINDEX('.',name)) AS INT) --Get the number after the dot
Perhaps, more verbal, but should do the trick
declare #source as table(num varchar(12));
insert into #source(num) values('K1.1'),('K1.10'),('K1.2'),('K3.1'),('K3.14'),('K3.5');
-- create helper table
with data as
(
select num,
cast(SUBSTRING(replace(num, 'K', ''), 1, CHARINDEX('.', num) - 2) as int) as [first],
cast(SUBSTRING(replace(num, 'K', ''), CHARINDEX('.', num), LEN(num)) as int) as [second]
from #source
)
-- Select and order accordingly
select num
from data
order by [first], [second]
sqlfiddle:
http://sqlfiddle.com/#!6/a9b06/2
The shorter solution is this one :
Select Num
from yourtable
order by cast((Parsename(Num, 1) ) as Int)
I need to transpose (I hope the word transpose is correct) a string of letter into a two letter in one column
the data I have is as follows: it is basically a two letter code mixed in together, very messy
ColumnID
HG34
HG/WK
HG\34
54/OF
AS\MM
AC54
AC54MM
and what I would like to do so to convert above into below:
ColumnID
HG
34
WK
54
OF
AS
MM
AC
is there a query that can do that?
I don't mind if the result has duplicates as I can always clean it up later
Thank you
select substring(ColumnID, 1, 2) from your_table
union
select substring(replace(replace(ColumnID,'\\',''),'/',''), 3, 2) from your_table
union
select substring(replace(replace(ColumnID,'\\',''),'/',''), 5, 2) from your_table
where length(replace(replace(ColumnID,'\\',''),'/','')) = 6
SQLFiddle demo
select distinct substring(col, x*2-1, 2)
from your_table
cross apply (select replace(replace(ColumnID,'\',''),'/',''))c(col)
inner join (values(1),(2),(3))x(x) on len (col) >= x * 2 -- as much pairs as needed
I need select only strings in my table, but this table has numbers and strings together.
Ex:
ID Name
1 Jacke11
2 Andre
3 Rodrigo11
4 55555
My select need return only Ids: 1, 2, 3.
Thanks
SELECT ID
FROM YourTable
WHERE ISNUMERIC(Name + '.0e0') = 0
As an alternative to Joe's very fine ISNUMERIC solution, you can use PATINDEX to make sure you have an alpha character:
SELECT ID
FROM YourTable
WHERE PATINDEX('%[a-z]%', name) > 0
This may be slightly faster since it will stop searching the string as soon as it gets to the first alpha character.