Is there a LEFT function in kql? - kql

In SQL, in order to grab n characters from the left side of a string, you can use the LEFT function:
SELECT LEFT('Hello World', 5)
-- "Hello"
There doesn't appear to be a left or right function in the docs on scalar functions:
Q: How do you do select left most characters in KQL?

You can use the substring function:
substring(source, startingIndex [, length])
LEFT
SQL: SELECT LEFT('Hello World', 5)
KQL: print substring("Hello World", 0, 5)
RIGHT
SQL: SELECT RIGHT('Hello World', 5)
KQL: print substring("Hello World", -5, 5)

Related

How to split a string having values "." seperated in SQL

For Eg; abc.def.efg , separate into independent strings as abc def efg
Head
abc.def.efg
to
left
center
right
abc
def
efg
On SQL Server with a 3-part delimited string you can use parsename
with t as (
select 'left.centre.right' Head
)
select ParseName(Head,3) L, ParseName(Head,2) C, ParseName(Head,1) R
from t;
on MySQL, you can do:
with t as (
select 'left.centre.right' Head
)
select
substring_index(Head,'.',1) as L,
substring_index(substring_index(Head,'.',2),'.',-1) as M,
substring_index(Head,'.',-1) as R
from t;
results:
L
M
R
left
centre
right
see: DBFIDDLE, and DOCS
Look into the split_part() equivalent for the RDBMS you're using.
E.g.
SELECT
split_part(Head, '.', 1) AS "left",
split_part(Head, '.', 2) AS center,
split_part(Head, '.', 3) AS "right"
FROM your_table
EDIT: corrected the indexes, see: https://www.postgresqltutorial.com/postgresql-split_part/

Print each character of a word line by line using a SQL query

I am giving input word is "hello"
My output will be print as mentioned below using SQL query not pl/sql.
h
e
l
l
o
You can use SUBSTR() function within a hierarchical query such as
SELECT SUBSTR(col,level,1) AS "letters"
FROM t
CONNECT BY level <= LENGTH(col)
presuming your DB is Oracle from the keyword PL/SQL
Use like this
select substring(a.b, v.number+1, 1)
from (select 'hellow' b) a
join master..spt_values v on v.number < len(a.b)
where v.type = 'P'
You didn't mention your DBMS, but in Postgres you can use:
select *
from unnest(string_to_array('hello', null));
Here is another way to do this in oracle
select 'hello'
,substr('hello',rownum,1) as vertical_str
from dual a
join all_tables b
on 1=1
where rownum<=length('hello')
h
e
l
l
o
Another option is a recursive CTE.
WITH
word
(word)
AS
(
SELECT 'hello' word
FROM dual
),
letter
(letter,
remainder)
AS
(
SELECT substr(word, 1, 1) letter,
substr(word, 2) remainder
FROM word
UNION ALL
SELECT substr(remainder, 1, 1) letter,
substr(remainder, 2) remainder
FROM letter
WHERE remainder IS NOT NULL
)
SELECT letter
FROM letter;
db<>fiddle
I am assuming Oracle here as you mentioned PL/SQL. But for other DBMS this would be pretty similar -- the substr() function might be called substring(), instead of a NULL you'd have to check for remainder to be the empty string and the RECURESIVE keyword might be needed for the second CTE.

Convert eastern arabic numerals to western arabic in bigquery

I have a problem where a eastern-arabic numeral has entered my table as a timestamp and bigquery doesn't recognise this as a timestamp and will not execute my queries.
I wish to be able to convert this:
'٢٠١٨-١٠-١١T١٦:٠١:٤١.٠٤١Z'
into this:
'2018-10-11T16:01:41.041Z
in bigquery, Is this possible?
How about this SQL UDF:
CREATE TEMP FUNCTION arabicConvert(input STRING) AS ((
SELECT STRING_AGG(COALESCE(FORMAT('%i', i), letter), '')
FROM (SELECT SPLIT(input, '') x), UNNEST(x) letter
LEFT JOIN (SELECT letter_dict,i FROM (
SELECT SPLIT('٠١٢٣٤٥٦٧٨٩', '') l), UNNEST(l) letter_dict WITH OFFSET i
)
ON letter=letter_dict
));
SELECT arabicConvert('٢٠١٨-١٠-١١T١٦:٠١:٤١.٠٤١Z') converted
2018-10-11T16:01:41.041Z
There is alternative, lighter option :o)
CREATE TEMP FUNCTION arabicNumeralsConvert(input STRING) AS ((
CODE_POINTS_TO_STRING(ARRAY(
SELECT IF(code > 1600, code - 1584, code)
FROM UNNEST(TO_CODE_POINTS(input)) code
))
));
WITH t AS (
SELECT '٢٠١٨-١٠-١١T١٦:٠١:٤١.٠٤١Z' str UNION ALL
SELECT '2018-10-12T20:34:57.546Z'
)
SELECT str, arabicNumeralsConvert(str) converted
FROM t
result is as
str converted
٢٠١٨-١٠-١١T١٦:٠١:٤١.٠٤١Z 2018-10-11T16:01:41.041Z
2018-10-12T20:34:57.546Z 2018-10-12T20:34:57.546Z

Regex pattern inside REPLACE function

SELECT REPLACE('ABCTemplate1', 'Template\d+', '');
SELECT REPLACE('ABC_XYZTemplate21', 'Template\d+', '');
I am trying to remove the part Template followed by n digits from a string. The result should be
ABC
ABC_XYZ
However REPLACE is not able to read regex. I am using SQLSERVER 2008. Am I doing something wrong here? Any suggestions?
SELECT SUBSTRING('ABCTemplate1', 1, CHARINDEX('Template','ABCTemplate1')-1)
or
SELECT SUBSTRING('ABC_XYZTemplate21',1,PATINDEX('%Template[0-9]%','ABC_XYZTemplate21')-1)
More generally,
SELECT SUBSTRING(column_name,1,PATINDEX('%Template[0-9]%',column_name)-1)
FROM sometable
WHERE PATINDEX('%Template[0-9]%',column_name) > 0
You can use substring with charindex or patindex if the pattern being looked for is fixed.
select SUBSTRING('ABCTemplate1',1, CHARINDEX ( 'Template' ,'ABCTemplate1')-1)
My answer expects that "Template" is enough to determine where to cut the string:
select LEFT('ABCTemplate1', CHARINDEX('Template', 'ABCTemplate1') - 1)
Using numbers table..
;with cte
as
(select 'ABCTemplate1' as string--this can simulate your table column
)
select * from cte c
cross apply
(
select replace('ABCTemplate1','template'+cast(n as varchar(2)),'') as rplcd
from
numbers
where n<=9
)
b
where c.string<>b.rplcd
Using Recursive CTE..
;with cte
as
(
select cast(replace('ABCTemplate21','template','') as varchar(100)) as string,0 as num
union all
select cast(replace(string,cast(num as varchar(2)),'') as varchar(100)),num+1
from cte
where num<=9
)
select top 1 string from cte
order by num desc

Parsing with substring returning wrong value

I have this query which tries to capture the last 11 characters excluding the semi colon at the end of the date(string). But when I run the script it returns value which is not included in the string, and im stuck for days.
Here's my query
select TOP 2 a.ACCOUNT,a.GPSDATE,
SUBSTRING(b.smsmsg, LEN(b.smsmsg) - 10, 6) [KM2]
from TblGPSCur a
inner join GPRSIN b on a.ACCOUNT = b.SMSFR
where exists(select * from GPRSIN b where b.SMSFR = a.ACCOUNT
and b.smsdt between '2014-10-27 14:00:00' and '2014-10-27 14:49:54')
THE RESULT IS THIS
This is the top 2 data im trying to parse
The result should be 277511767.8
Can anyone tell me where I might be doing wrong on this one?
You can use RIGHT() function of SQL like this -
SELECT TOP 2 a.ACCOUNT
,a.GPSDATE
RIGHT(b.smsmsg, 11) [KM2]
FROM TblGPSCur a
INNER JOIN GPRSIN b ON a.ACCOUNT = b.SMSFR
WHERE EXISTS (
SELECT *
FROM GPRSIN b
WHERE b.SMSFR = a.ACCOUNT
AND b.smsdt BETWEEN '2014-10-27 14:00:00'
AND '2014-10-27 14:49:54'
)
You have your SUBSTRING() setup incorrectly, it should be:
SELECT SUBSTRING(b.smsmsg, LEN(b.smsmsg) - 11, 11)
As the starting position is LEN(x) - 11, and you want 11 characters after that point.
Alternately, you can use LEFT() and RIGHT():
declare #SillyLongString as nvarchar(100)
set #SillyLongString = '1234567890a;s.a.dpoiuytghjkmnbvfg,277511767.8;'
select left(right(#SillyLongString, 12),11)
-- outputs: 277511767.8
This selects the 12 right-most characters and then takes the first 11 characters from that string.
Adding to your query:
select TOP 2 a.ACCOUNT,a.GPSDATE,
left(right(b.smsmsg, 12),11) [KM2] ...