How to query a value of a numrange field? - postgresql

I have a numrange field that as below:
A [0,100)
B [101,200)
How to query based on a value, ie. 110 -> it will returns B ..
I try:
select * From escalation_limit Where range_limit::numrange #>110::numrange
it returns:
ERROR: cannot cast type integer to numrange
LINE 1: ... escalation_limit Where range_limit::numrange #>110::numrange

You can use the contains operator #>:
select *
from the_table
where the_range_column #> 110::numeric;

Related

Cast integer to decimal in DQL

I use Doctrine with a Postgres database and want to update the integer field "voting".
It's a procentual value, saved as integer between 0 and 100, based on the two integer fields "voteCountPro" and "voteCount".
I have to cast one of the integers to a decimal value. (See: Division ( / ) not giving my answer in postgresql)
This doesn't work in DQL and fails with the message:
[Syntax Error] line 0, col 363: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ':'
UPDATE statement s
SET s.voting = (s.voteCountPro::decimal / s.voteCount) * 100
WHERE s.id = :id
How can I set the value?
Install https://github.com/oroinc/doctrine-extensions, register the CAST function and write:
UPDATE statement s
SET s.voting = (CAST(s.voteCountPro as decimal) / s.voteCount) * 100
WHERE s.id = :id

Get cutted JSON in query

I have a column in db which constains JSON values like:
{"key-1": "val-1", "key-2": "val-2", "key-3": "val-3"}
By query like..
SELECT column->>'key-1' FROM table;
I can get my val-1.
Is there a way to get value with key as JSON in sql query from already existed JSON value?
I want to get result like:
{"key-1": "val-1"}
from
{"key-1": "val-1", "key-2": "val-2", "key-3": "val-3"}
using sql query.
Use ampersand operator, &, e.g.,
Live test: https://www.db-fiddle.com/f/9izCEH75JhwVDvsGvsZomG/0
with the_table as
(
select '{"key-1": "val-1", "key-2": "val-2", "key-3": "val-3"}'::jsonb as d
)
select d & 'key-1' as j from the_table
Output:
| j |
| ----------------- |
| {"key-1":"val-1"} |
Just kidding :) Create a function that extracts the desired key value pair, and then create your own user-defined operator for it.
create or replace function extract_one_jsonb(j jsonb, key text)
returns jsonb
as
$$
select jsonb_build_object(key, j->key)
$$ language sql;
create operator & (
leftarg = jsonb,
rightarg = text,
procedure = extract_one_jsonb
);
Of course you can just use a function, or if creating a user-defined operator is not an option:
with the_table as
(
select '{"key-1": "val-1", "key-2": "val-2", "key-3": "val-3"}'::jsonb as d
)
select extract_one_jsonb(d, 'key-1') as j from the_table
Output:
| j |
| ----------------- |
| {"key-1":"val-1"} |
If extracting a key value pair from jsonb is being done many times, it's desirable to give an operator for it, e.g., &. Postgres is pretty flexible when you want to create your own operator, this can be created too: ->>>.
Live test: https://www.db-fiddle.com/f/9izCEH75JhwVDvsGvsZomG/1
create operator ->>> (
leftarg = jsonb,
rightarg = text,
procedure = extract_one_jsonb
);
Output:
| j |
| ----------------- |
| {"key-1":"val-1"} |
->> is already used by Postgres: https://www.postgresql.org/docs/11/functions-json.html
You can create '->>>' instead. ->>> looks more like an extractor operator than ampersand &. Besides it looks good even you stick it to the source field (that is without spaces)
with the_table as
(
select '{"key-1": "val-1", "key-2": "val-2", "key-3": "val-3"}'::jsonb as d
)
select d->>>'key-1' as j from the_table
Tried the following, it works too, looks like a scissor (for cutting): %>
select d%>'key-1' as j from the_table
The only thing I can think of is to get the key/value pair and assemble that back into a single JSON value:
select jsonb_build_object(j.k, j.v)
from the_table t, jsonb_each(t.json_col) as j(k,v)
where j.k = 'key-1'
and ... more conditions ...;
Online example: https://rextester.com/VGSX43955

PostgreSQL ERROR: invalid input syntax for integer: "1e+06"

The full error message is:
ERROR: invalid input syntax for integer: "1e+06"
SQL state: 22P02
Context: In PL/R function sample
The query I'm using is:
WITH a as
(
SELECT a.tract_id_alias,
array_agg(a.pgid ORDER BY a.pgid) as pgids,
array_agg(a.sample_weight_geo ORDER BY a.pgid) as block_weights
FROM results_20161109.block_microdata_res_joined a
WHERE a.tract_id_alias in (66772, 66773, 66785, 66802, 66805, 66806, 66813)
AND a.bldg_count_res > 0
GROUP BY a.tract_id_alias
)
SELECT NULL::INTEGER agent_id,
a.tract_id_alias,
b.year,
unnest(shared.sample(a.pgids,
b.n_agents,
1 * b.year,
True,
a.block_weights)
) as pgid
FROM a
LEFT JOIN results_20161109.initial_agent_count_by_tract_res_11 b
ON a.tract_id_alias = b.tract_id_alias
ORDER BY b.year, a.tract_id_alias, pgid;
And the shared.sample function I'm using is:
CREATE OR REPLACE FUNCTION shared.sample(ids bigint[], size integer, seed integer DEFAULT 1, with_replacement boolean DEFAULT false, probabilities numeric[] DEFAULT NULL::numeric[])
RETURNS integer[] AS
$BODY$
set.seed(seed)
if (length(ids) == 1) {
s = rep(ids,size)
} else {
s = sample(ids,size, with_replacement,probabilities)
}
return(s)
$BODY$
LANGUAGE plr VOLATILE
COST 100;
ALTER FUNCTION shared.sample(bigint[], integer, integer, boolean, numeric[])
OWNER TO "server-superusers";
I'm pretty new to this stuff, so any help would be appreciated.
Not a problem of the function. Like the error messages says: The string '1e+06' cannot be cast to integer.
Obviously, the columns n_agents in your table results_20161109.initial_agent_count_by_tract_res_11 is not an integer column. Probably type text or varchar? (That info would help in your question.)
Either way, the assignment cast does not work for the target type integer. But it does for numeric:
Does not work:
SELECT '1e+06'::text::int; -- error as in question
Works:
SELECT '1e+06'::text::numeric::int;
If my assumptions hold, you can use this as stepping stone.
Replace b.n_agents in your query with b.n_agents::numeric::int.
It's your responsibility that numbers stay in integer range, or you get the next exception.
If that did not nail it, you need to look into function overloading:
Is there a way to disable function overloading in Postgres
And function type resolution:
PostgreSQL function call
The schema search path is relevant in many related cases, but you did schema-qualify all objects, so we can rule that out.
How does the search_path influence identifier resolution and the "current schema"
Your query generally looks good. I had a look and only found minor improvements:
SELECT NULL::int AS agent_id -- never omit the AS keyword for column alias
, a.tract_id_alias
, b.year
, s.pgid
FROM (
SELECT tract_id_alias
, array_agg(pgid) AS pgids
, array_agg(sample_weight_geo) AS block_weights
FROM ( -- use a subquery, cheaper than CTE
SELECT tract_id_alias
, pgid
, sample_weight_geo
FROM results_20161109.block_microdata_res_joined
WHERE tract_id_alias IN (66772, 66773, 66785, 66802, 66805, 66806, 66813)
AND bldg_count_res > 0
ORDER BY pgid -- sort once in a subquery. cheaper.
) sub
GROUP BY 1
) a
LEFT JOIN results_20161109.initial_agent_count_by_tract_res_11 b USING (tract_id_alias)
LEFT JOIN LATERAL
unnest(shared.sample(a.pgids
, b.n_agents
, b.year -- why "1 * b.year"?
, true
, a.block_weights)) s(pgid) ON true
ORDER BY b.year, a.tract_id_alias, s.pgid;

Comparing two fileds in select command

I am trying to select all records from Transaction_Table where Tr_Amount = Instrument_Number using following Code
Select * from Transaction_Table
where abs(Tr_Amount) = Cast(Instrument_number as INTEGER)
However there are some rows in the table where Instrument_Number is Alphanumeric instead of Just Numeric Data. I there a way to skip the alphanumeric instances in Instrument_Number field in the command.
Switch to TO_NUMBER, which returns NULL for bad data:
Select * from Transaction_Table
where abs(Tr_Amount) = TO_NUMBER(Instrument_number)
TD15.10 implements a TRYCAST:
Select * from Transaction_Table
where abs(Tr_Amount) = TRY_CAST(Instrument_number as INTEGER)

invalid input syntax for integer: "1" postgresql

PostgreSql gives me this error when i try to cast a TEXT colum to a integer.
select pro_id::integer from mmp_promocjas_tmp limit 1;
This colum contains only digits, valid integer. How can "1" be invalid integer?
select pro_id, length(pro_id) ,length(trim(pro_id)) from mmp_promocjas_tmp limit 1;
outputs:
1 | 2 | 2
Query select pro_id from mmp_promocjas_tmp where trim(pro_id) = '1' shows nothing.
I tried to remove whitespaces, without no result:
select pro_id from mmp_promocjas_tmp where regexp_replace(trim(pro_id), '\s*', '', 'g')
There are probably spurious invisible contents in the column.
To make them visible, try a query like this:
select pro_id, c,lpad(to_hex(ascii(c)),4,'0') from (
select pro_id,regexp_split_to_table(pro_id,'') as c
from (select pro_id from mmp_promocjas_tmp limit 10) as s
) as g;
This will show the ID and each character its contains, both as a character and as its hexadecimal code in the repertoire.