Cast character to int in order to query properly - postgresql-9.5

I need to select a range of values (eg : "1", "2", "2A", "3", ...) in a column but these are character varying so I must cast them to int in order to get a proper "BETWEEN" evaluation.
This is what I tried but it seems it ignores the cast, returning only values corresponding to numins = 1001 :
SELECT sum(totalchiefs) AS totalchiefs
, sum(totalnochiefs) AS totalnochiefs
, sum(totalchildrens) AS totalchildrens
, sum(totalpeople) AS totalpeople
FROM nombrehabs
WHERE numins = 1001 AND ((numpol~E'^\\d+$')::integer BETWEEN 1 AND 27);

You could use the substring function to extract the number from your strings.
SELECT
SUM( totalchiefs ) AS totalchiefs,
SUM ( totalnochiefs ) AS totalnochiefs,
SUM ( totalchildrens ) AS totalchildrens,
SUM ( totalpeople ) AS totalpeople
FROM
nombrehabs
WHERE
numins = 1001
AND (SUBSTRING(numpol FROM '\d+') :: INTEGER BETWEEN 1 AND 27)
);
Checkout the documentation at 9.7. Pattern Matching

Related

BIGQUERY An internal error occurred and the request could not be completed Error: 80038528

I am trying to install a function. I don't understand what the problem is. I can install correctly when:
I delete the pivot
I use the Table and not the unnest only (so from the table, unnest(a))
CREATE OR REPLACE FUNCTION `dataset.function_naming` (a ARRAY<STRUCT<ROW_ID STRING, KEY STRING, VALUE STRING>>, id_one STRING, id_two STRING, start_date DATE, end_date DATE) RETURNS INT64
AS (
with tmp1 as (
select ROW_ID,X,Y,Z,W
from
(
select prop.ROW_ID,prop.KEY, prop.VALUE
from unnest(a) prop
where prop.KEY in ('X','Y','Z','W')
)
PIVOT
(
MAX(VALUE)
FOR UPPER(KEY) in('X','Y','Z','W')
) as PIVOT
)
select case when X is not null then 1,
when Y is not null then 2,
when Z is not null then 2,
when W is not null then 2
else 0
from tmp1
);
Thanks all.
There are few minor issues I see in your code.
missing extra (...) around function body
extra commas (,) within case statement
So, try below
CREATE OR REPLACE FUNCTION `dataset.function_naming` (
a ARRAY<STRUCT<ROW_ID STRING, KEY STRING, VALUE STRING>>,
id_one STRING,
id_two STRING,
start_date DATE,
end_date DATE
) RETURNS INT64
AS ((
with tmp1 as (
select ROW_ID,X,Y,Z,W
from
(
select prop.ROW_ID,prop.KEY, prop.VALUE
from unnest(a) prop
where prop.KEY in ('X','Y','Z','W')
)
PIVOT
(
MAX(VALUE)
FOR UPPER(KEY) in('X','Y','Z','W')
) as PIVOT
)
select case when X is not null then 1
when Y is not null then 2
when Z is not null then 2
when W is not null then 2
else 0
end
from tmp1
));
Seams there is an internal issue when using pivots and the unnest on the array. You can use the following, that executes the same logic, and also, create an case on issue tracker, as a BigQuery issue with Google cloud Support.
CREATE OR REPLACE FUNCTION `<dataset>.function_naming` (
a ARRAY<STRUCT<ROW_ID STRING, KEY STRING, VALUE STRING>>,
id_one STRING,
id_two STRING,
start_date DATE,
end_date DATE
) RETURNS INT64
AS (( WITH tmp AS (
SELECT
CASE
WHEN KEY="X" THEN 1
WHEN KEY="Y" THEN 2
WHEN KEY="Z" THEN 2
WHEN KEY="W" THEN 2
ELSE
0
END
teste_column
#-- FROM ( SELECT UPPER(prop.KEY) KEY, MAX(prop.VALUE) VALUE FROM -- following your query patern, but not really necessary
FROM ( SELECT UPPER(prop.KEY) KEY FROM
UNNEST(a) prop
WHERE
UPPER(key) IN ('X', 'Y', 'Z', 'W')
GROUP BY key )
ORDER BY teste_column DESC LIMIT 1 )
SELECT * FROM tmp
UNION ALL
SELECT 0 teste_column
FROM (SELECT 1)
LEFT JOIN tmp
ON FALSE
WHERE NOT EXISTS ( SELECT 1 FROM tmp)
));
#--- Testing the function:
select `<project>.<dataset>.function_naming`([STRUCT("1" AS ROW_ID, "x" AS KEY, "10"AS VALUE), STRUCT("1" AS ROW_ID, "x" AS KEY, "20"AS VALUE), STRUCT("1" AS ROW_ID, "w" AS KEY, "20"AS VALUE), STRUCT("1" AS ROW_ID, "y" AS KEY, "20"AS VALUE)], "1", "2", "2022-12-10", "2022-12-10")

How to find the number of continuous times a character appears in a string

I have a string 11111122111131111111
I want to create an array of the number of times 1 appears continuously i.e. first 6 characters are 1s -> two 2's -> four 1's -> one 3 -> seven 1's
So the output that i want is [6,4,7]
I know how to find the number of times a character appears in a string but how to find the numbers of times they appear in a contiguous patter.
Below example is for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.table` AS (
SELECT '11111122111131111111' line
)
SELECT line, ARRAY(SELECT LENGTH(e) FROM UNNEST(REGEXP_EXTRACT_ALL(line, r'1+')) e) result
FROM `project.dataset.table`
with result
[
{
"line": "11111122111131111111",
"result": [
"6",
"4",
"7"
]
}
]
A little unclear as to the actual RDBMS
Here we use an ad-hoc tally table (any table of adequate size will do). Then we apply a standard Gaps-and-Islands.
Example
Declare #S varchar(500) = '11111122111131111111'
Declare #C varchar(10) = '1'
Select Seq=Row_Number() over (Order by Seq)
,Cnt=count(*)
From (
Select N
,S = substring(#S,N,1)
,Seq = N - Row_Number() over (Order by N)
From ( Select Top (len(#S))
N=Row_Number() Over (Order By (Select NULL))
From master..spt_values n1
) A
Where substring(#S,N,1)=#C
) A
Group By Seq
Order By Seq
Returns
Seq Cnt
1 6
2 4
3 7
;WITH splitString(val) AS
(
-- convert the string to xml, seperating the elements by spaces
SELECT CAST('<r><i>' + REPLACE(#string,' ','</i><i>') + '</i></r>' AS XML)
)
SELECT [Key],
COUNT(*) [WordCount]
FROM ( -- select all of the values from the xml created in the cte
SELECT p.value('.','varchar(100)') AS [Key]
FROM splitString
CROSS APPLY val.nodes('//i') t (p)) AS t
GROUP BY [Key]

SQL Server sorting odd numbers ASC and even numbers DESC

I am wondering if there is a way in SQL Server to sort a table which holds numbers in a varchar column. I went and cast the number (in my case House Numbers) to Int and use
order by cast([sano]%2 as int), cast([sano] as Int)
which actually creates the output of 2,4,6,8...,1,3,5,7,9 and so on. but I need to get the output like 2,4,6,8..9,7,5,3,1 so even is asc and then the odd is desc.
One trick is to use a case expression to multiply odd numbers by -1, and thus get the ones with the largest absolute value first in an ascending order:
ORDER BY CAST([sano] % 2 AS INT),
CAST([sano] AS INT) * CASE CAST([sano] % 2 AS INT) WHEN 0 THEN 1 ELSE -1 END
Assuming that there is a reasonable upper bound on a house number, you can use the following:
declare #Samples as Table ( HouseNumber Int );
insert into #Samples ( HouseNumber ) values
( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 ), ( 6 ), ( 7 ), ( 8 ), ( 9 );
select HouseNumber,
case HouseNumber % 2 when 0 then HouseNumber else 1000000 - HouseNumber end as SortValue
from #Samples
order by case HouseNumber % 2 when 0 then HouseNumber else 1000000 - HouseNumber end;
For even values it uses the house number. By flipping the sign of odd numbers they are sorted in the opposite order, but an offset is needed to have them sort after the even values.
This seems to work, but I have no idea why
select *
from test
order by CASE WHEN sano%2=0 THEN sano%2 END ASC
I am testing and investigating this behaviour

selecting the value from column having highest digit count after decimal places

I have the below table named SAXTION_EG and it this table contain various colulms out of which there is one column named STR_RATE and in this columncontain values like
STR_RATE
1.11317
123.08546759
8.49111
now please advise me the oracle query by which i can select the maximum value in terms of decimal point for example in the above mentioned case the value 123.08546759 has highest decinal count so it has 8 digits count after decimal, as my objective is to fetch the value having highest digit count after decimal
You can try some thing like this. Logic is first get the position of the decimal point. Then get the string after the decimal. After that count the no of chars in that substring. Then use the MAX to get the aggregated max value
SELECT MAX(LENGTH(SUBSTR(STR_RATE, INSTR(STR_RATE, '.')+ 1)))
FROM your_table
In the solution below, I assume str_rate is of data type NUMBER, so it must be converted to character first. I added a couple of sample values to check that integer values are treated correctly, and to illustrate a case when two values have the same, highest number of decimal digits. In this case the solution returns both such values (see result set at the bottom).
with
saxtion_eg ( str_rate ) as (
select 1.11317 from dual union all
select 123.08546759 from dual union all
select 8.49111 from dual union all
select 582 from dual union all
select 0.00000001 from dual
),
prep ( str_rate, char_rate, pos ) as (
select str_rate, to_char(str_rate), instr(to_char(str_rate), '.')
from saxtion_eg
),
final ( char_rate, dec_digits, max_dec_digits ) as (
select char_rate,
case pos when 0 then 0 else length(char_rate) - pos end,
max(case pos when 0 then 0 else length(char_rate) - pos end) over ()
from prep
)
select char_rate as str_rate
from final
where dec_digits = max_dec_digits
;
STR_RATE
----------------
123.08546759
.00000001
This query return the maximum value in terms of decimal point:
select max(STR_RATE) keep (dense_rank last order by length(STR_RATE-trunc(STR_RATE)))
from SAXTION_EG

Firebird CTE result dataset with insert statement

I do have the difficulties with the following code I couldn't find where to place the insert statement in that code where it will insert the returned values from the CTE.
insert into ntm (num,comb,0,0,0,0,0,0,0,0,0,0,0,0)
with CTE as (
SELECT a.ELM_NUM as num,
a.N_1 as N1,
(trim('1.4*'||a.COMBO)||' + ' || '1.6*'||b.COMBO) as com2,
b.ELM_NUM as num2
FROM NTM a cross join ntm b
where ((a.Combo='dead' and b.combo='live') or (a.Combo='dead' and b.combo='live')) and a.ELM_NUM=b.ELM_NUM)
select num, num2, trim(trim(com2)||' + '||trim(d.combo)), N1, 1.4*N1
from CTE cross join ntm d
where (d.elm_num = cte.num) and (position('X',combo)>0 or position('Y',combo)>0 )
error raised by FlameRobin Engine "Token unknown - line 1, column 27
0
CREATE TABLE NTM
(
ELM_NUM Integer NOT NULL,
COMBO Char(40) NOT NULL,
N_1 Double precision,
N_2 Double precision,
V2_1 Double precision,
V2_2 Double precision,
V3_1 Double precision,
V3_2 Double precision,
M2_1 Double precision,
M2_2 Double precision,
M3_1 Double precision,
M3_2 Double precision,
MT_1 Double precision,
MT_2 Double precision
);
You can insert the result of an select statement by adding INSERT INTO <table> (<column>[, <column>]*) before the select statement (including the WITH). So If you have a query:
WITH a AS (
SELECT 4 AS ID, 'Item 4' AS NAME FROM RDB$DATABASE
)
SELECT ID, NAME
FROM a
And you want to insert into a table ITEMS with columns ID and NAME:
INSERT INTO ITEMS (ID, NAME)
WITH a AS (
SELECT 4 AS ID, 'Item 4' AS NAME FROM RDB$DATABASE
)
SELECT ID, NAME
FROM a
This works on Firebird 2.5, but I assume it also works in Firebird 2.1.
Based on your edit:
Your syntax is simply wrong: insert into ntm (num,comb,0,0,0,0,0,0,0,0,0,0,0,0) is invalid: you don't have a columns num and comb in table ntm, and specifying 0 as a column name is illegal. It seems you are confusing the INSERT columnlist with a value-list.
The syntax of an INSERT is:
INSERT INTO <object> [(col [, col …])]
{VALUES (<val> [, <val> …]) | <select_expr>}
You try to use something like:
INSERT INTO <object> (<val> [, <val> …])
<select_expr>
Assuming you only want to insert the num (into ELM_NUM) and the trim(trim(com2)||' + '||trim(d.combo)) (into COMBO) columns from your select, you should use:
insert into ntm (ELM_NUM,COMBO)
with CTE as (
SELECT a.ELM_NUM as num,
a.N_1 as N1,
trim('1.4*'||a.COMBO)||' + ' || '1.6*'||b.COMBO as com2,
b.ELM_NUM as num2
FROM NTM a cross join ntm b
where (a.Combo='dead' and b.combo='live' or a.Combo='dead' and b.combo='live') and a.ELM_NUM=b.ELM_NUM
)
select num, trim(trim(com2)||' + '||trim(d.combo))
from CTE cross join ntm d
where d.elm_num = cte.num and (position('X',combo) > 0 or position('Y',combo) > 0)
Note that I removed the other columns from the select as you are not inserting those (the number of columns in the select list must match the number of columns in the insert column list).
If you want the remaining columns to be 0, you either need to add a DEFAULT 0 to the table definition, or you need to list all columns and add a 0 value in your select list for each of those additional columns.