Postgresql - VALUE between two columns - postgresql

I have a long list of six digit numbers (e.g. 123456)
In my postgresql DB I have a table with two columns start_value and end_value. The table has rows with start and end values which are 9 digits in length and represent a range of numbers i.e. start_value might be 123450000 and end_value might be 123459999.
I need to match each of the six digit numbers with it's row in the DB table which falls in its range.
For many numbers in my list I can simply run the following
SELECT * FROM table WHERE start_value=(number + 000)
However, this does not cover numbers which fall inside a range, but do not match this pattern.
I have been trying statements such as:
SELECT * FROM table WHERE start_value > (number + 000) AND end_value < (number + 999)
But this doesn't work because some rows cover larger ranges than xxxxx0000 to xxxxx9999 and so the statement above may return 20 rows or none.
Any points would be most welcome!
EDIT: the Data Type of the columns are numeric(25)

Assuming number is numeric:
select *
from table
where number * 1000 between start_value and end_value

Ok, so if I'm understanding correctly, first you need to pad your search value to 9 digits. You can do that with this - 12345 * (10 ^ (9 - length(12345::text))).
length(12345::text) gets the number of digits you currently have, then it subtracts that from 9 and multiplies your search value by 10 to the power of the result. Then you just throw it in your search. The resulting query looks something like this -
SELECT * FROM table WHERE (12345 * (10 ^ (9 - length(12345::text)))) > start_value AND (12345 * (10 ^ (9 - length(12345::text)))) < end_value
You could also use the BETWEEN operator, but it is inclusive, which doesn't match the example query you have.

POSTGRESQL
Some time we stuck in data type casting problems and null value exceptions.
SELECT *
FROM TABLE
WHERE COALESCE(number::int8, 0::int8) * 1000 BETWEEN start_value::int8 AND end_value::int8
;
number::int8 type cast to integer
start_value::int8 type cast to integer
COALESCE(number::int8, 0::int8)
return number or zero if value is empty to avoid exceptions

Related

Does my Postgresl column contain only digits?

Is there a way to check if a character varying type column contains only digits or null values with Postgresql?
Maybe something like (this syntax is incorrect):
SELECT *
FROM mytable
ORDER BY
CASE WHEN mycol ~ '^[0-9\.]+$' THEN 1 ELSE 0 END
LIMIT 1
I'm expecting TRUE or FALSE as final result for the whole column.
If you want to to know if the values in all rows are digits, you can use
select not exists (select *
from mytable
where not (mycol ~ '^[0-9\.]+$'))
Online example
To get Nulls use COALESCE(mycol, 1) -- will return 1 if the value in mycol is NULL.
For checking numerics you could use regex LIKE'^[0-9]*' it wont detect decimal dots (dont know if your data have decimals)
BR!

How should I query an integer where there are decimals in the data?

SELECT * FROM table1 WHERE spent>= '1000'
This query still bring out numbers such as 598.99 and 230.909. My question is why is it doing this when I asked to search over or equal to 1000. Is there anyway to query so it only shows equal and more than 1000?
This happens because your '1000' is a text value. The other value is (or is converted to) text, too, so you end up with byte-per-byte comparison.
598.99 is greater then 1000 because 5... is greater then 1....
Cast to numeric types to do a proper comparison:
SELECT * FROM table1 WHERE spent::numeric >= '1000'::numeric
Or simply:
SELECT * FROM table1 WHERE spent::numeric >= 1000
You must compare numbers to get numeric comparison.
Use
WHERE CAST(spent AS numeric) >= 1000

How to replace last 5 digits of afield with '99999' using update query?

I have one column. In that column all rows are having 10 digits i.e. 1234567890. By using PostgreSQL update query, I need to update last 5 digits to 99999. i.e. 1234599999
Can any one provide me update query for above requirement.
Integer divide your number by 100,000 (i.e. discard the remainder), multiply it by 100,000 then add 99,999:
UPDATE table SET field = FLOOR(field / 100000) * 100000 + 99999;
UPDATE table name SET column name = column name:: int / 10000 * 10000 + 9999 WHERE column name!=''''
Here column name having varchar data type I converted to int as per my requirement.

numeric range data type postgresql

I have a strange situation in the desing of my DB. I have the case that the type of value of a field can be a normal integer or a number between a range. I explain myself with a example:
the column age can be a number (18) or a range between (18-30). How I can represent this with postgresql?
Thx!
An integer range can represent both a single integer value and a range. The single value:
select int4range(18,18,'[]');
int4range
-----------
[18,19)
The ")" in the result above means exclusive.
The range:
select int4range(18,30,'[]');
int4range
-----------
[18,31)
There are a couple different ways to do this.
Store a VARCHAR
Store two values lower bound and upper bound
If there are only a select set of ranges you can create a lookup table for that set and store a foreign key to that lookup table.
You can make a bigger number, for example 18 x 1000 + 0 = 18000 for 18 and 18 x 1000 + 30 = 18030 for (18, 30).
When you retrieve it, you do first = round(number/1000) for the first number and second = number - first for the second number.
You can also store them as a point http://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6730.

Divide records into groups - quick solution

I need to divide with UPDATE command rows (selected from subselect) in PostgreSQL table into groups, these groups will be identified with integer value in one of its columns. These groups should be with the same size. Source table contains billions of records.
For example I need to divide 213 selected rows into groups, every group should contains 50 records. The result will be:
1 - 50. row => 1
51 - 100. row => 2
101 - 150. row => 3
151 - 200. row => 4
200 - 213. row => 5
There is no problem to do it with some loop (or use PostgreSQL window functions), but I need to do it very efficiently and quickly. I can't use sequence in id because there should be gaps in these ids.
I have an idea to use random integer number generator and set it as default value for a row. But this is not useable when I need to adjust group size.
The query below should display 213 rows with a group-number from 0-4. Just add 1 if you want 1-5
SELECT i, (row_number() OVER () - 1) / 50 AS grp
FROM generate_series(1001,1213) i
ORDER BY i;
create temporary sequence s minvalue 0 start with 0;
select *, nextval('s') / 50 grp
from t;
drop sequence s;
I think it has the potential to be faster than the row_number version #Richard. But the difference could be not relevant depending on the specifics.