PostgreSQL unable to divide? - php

I'm recently migrating from MySQL to Postgres, as I am now running a OSM tile server that requires Postgres / Postgis in order to function, and I see no reason to waste RAM by having 2 databases running at the same time. I am noticing many nuances in Postgres but one thing that bugs me is division does not seem to be working. I can not divide! Am I doing something wrong here? 197/201 should return 0.980099502
Core=# SELECT SUM(197/201);
sum
-----
0
(1 row)
Core=# SELECT SUM(197+201);
sum
-----
398
(1 row)
Core=# SELECT SUM(197*201);
sum
-------
39597
(1 row)
Core=# SELECT SUM(197-201);
sum
-----
-4
(1 row)

Postgres does integer division, so 1/2 = 0. You can try to add a decimal point to get another answer, 1.0/2.
You can read the documentation here.

Related

PHP Get peak from dataset with value and timestamp

I need to get the peak from a dataset using PHP. This dataset is made with timestamp and value. I need to get the 3 peak like the image with the 3 relative timestamp
This is a graphic rappresentation of the dataset:
But i don't need to rappresentate graphically, i'd like just a simple return of an array of the three value/timestamp. I need also a sort of threshold for avoid flase positive peak, for example minimum variation like from 0 to 400 (i'll define it in case but i need a threshold)
You can find the example dataset here:
https://wetransfer.com/downloads/d7d20a726285ea29ae2ff682764b045020210401192032/13e788
Many thanks for the help, i'm stuck with this. I have searched on Stackoverflow, i have see some algorithm but i cant apply to my necessity
I think that your sample data size suggests a database as a proper tool for the job. So assuming that data is already stored in table readings with two numeric columns - ts and reading, then this query may help.
select ts, reading
from
(
select ts, reading, lag(reading) over (order by ts) as variation from readings
) as t
where variation < 400 -- or whatever your threshold value may be
order by reading desc
limit 3;
This is Postgresql dialect that I am most comfortable with. You can re-write it in another SQL dialect if necessary and then easily pull the result data in PHP using PDO for example.

MySQL (MariaDB) execution timeout within query called from PHP

I'm stress testing my database for a geolocation search system. It has a lot of optimisation built in already such a square box long/lat index system to narrow searches before performing arc distance calculations. My aim is to serve 10,000,000 users from one table.
At present my query time is between 0.1 and 0.01 seconds based on other conditions such as age, gender etc. This is for 10,000,000 users evenly distributed across the UK.
I have a LIMIT condition as I need to show the user X people, where X can be between 16 and 40.
The issue is when there are no other users / few users that match, the query can take a long time as it cannot reach the LIMIT quickly and may have to scan 400,000 rows.
There may be other optimisation techniques which I can look at but my questions is:
Is there a way to get the query to give up after X seconds? If it takes more than 1 second then it is not going to return results and I'm happy for this to occur. In pseudo query code it would be something like:
SELECT data FROM table WHERE ....... LIMIT 16 GIVEUP AFTER 1 SECOND
I have thought about a cron solution to kill slow queries but that is not very elegant. The query will be called every few seconds when in production so the cron would need to be on continuously.
Any suggestions?
Version is 10.1.14-MariaDB
Using MariaDB in version 10.1, you have two ways of limiting your query. It can be done based on time or on total of rows queried.
By rows:
SELECT ... LIMIT ROWS EXAMINED rows_limit;
You can use the keyword EXAMINED and set an amount of lines like 400000 as you mentioned (since MariaDB 10.0).
By time:
If the max_statement_time variable is set, any query (excluding stored
procedures) taking longer than the value of max_statement_time
(specified in seconds) to execute will be aborted. This can be set
globally, by session, as well as per user and per query.
If you want it for a specific query, as I imagine, you can use this:
SET STATEMENT max_statement_time=1 FOR
SELECT field1 FROM table_name ORDER BY field1;
Remember that max_statement_time is set in seconds (just the opposite of MySQL, which are milliseconds), so you can change it until you find the best fit for your case (since MariaDB 10.1).
If you need more information I recommend you this excellent post about queries timeouts.
Hope this helps you.

MySQL SUM returning unnecessary decimals

I have single record on a table. So on MySQL when
select myamount from table 1 -- returns amount 420.67
But when i do MySQL as
select sum(myamount) from table 1 -- returns amount 420.8699951171875
should n't it return same amount 420.67 since I have only one record? and how to get amount 420.67 if SUM used.
Any help is appreciated and yes myamount datatype is float.
Float variables are stored in "scientific notation" (the 2,4E+04 format, which is the same as 2,4*10^4). But to make it even worse, it is also stored in binary. When calculating things with numbers stored as float, you may get a bit strange results because of this.
This video by Computerphile describes the problem very nicely.

Finding Interval of a data present on latest 2 dates

I'm developing a web-based tool that can help analyze number intervals that occurs in a 6-digit lottery.
Let us focus on a certain number first. Say 7
The sql query I've done so far:
SELECT * FROM `l642` WHERE `1d`=7 OR `2d`=7 OR `3d`=7 OR `4d`=7 OR `5d`=7
OR `6d`=7 ORDER BY `draw_date` DESC LIMIT 2
This will pull the last two latest dates where number 7 is present
I'm thinking of using DATEDIFF but I'm confused on how to get the previous value to subtract it on the latest draw_date
My goal is to list the intervals of numbers 1-42 and I'll plan to accomplish it using PHP.
Looking forward to your help
A few ideas spring to mind.
(1) First, since you perfectly have your result set ordered, use PHP loop on the two rows getting $date1 =$row['draw_date']. Then fetch next/last row and set $date2 =$row['draw_date']. With these two you have
$diff=date_diff($date1,$date2);
as the difference in days.
(2)
A second way is to have mysql return datediff by including a rownumber in the resultset and doing a self-join with aliases say alias a for row1 and alias b for row2.
datediff(a.draw_date,b.drawdate).
How one goes about getting rownumber could be either:
(2a) rownumber found here: With MySQL, how can I generate a column containing the record index in a table?
(2b) worktable with id int auto_increment primary key column with select into from your shown LIMIT 2 query (and a truncate table worktable between iterations 1 to 42) to reset auto_increment to 0.
The entire thing could be wrapped with an outer table 1 to 42 where 42 rows are brought back with 2 columns (num, number_of_days), but that wasn't your question.
So considering how infrequent you are probably doing this, I would probably recommend not over-engineering it and would shoot for #1

SQL - Query Help: Finding a Local Maximum

I have a table which has data from a graph.
for example
index value
0 3
1 5
2 7
3 6
4 8
5 9
6 12
7 11
8 10
9 14
10 13
I need to a query that returns the results where the value is at a local maximum, i.e. the value at a particular index is greater than the value at index+1 and index-1.
So for the example set, it should return the list of indexes: 2, 6, 9 corresponding to values 7, 12, 14.
I'm using PHP with SQLite.
I can do it with a foreach-loop in php, but was wondering if there's an easy way to do it using just SQL commands.
Any input would be appreciated.
Or use sub-queries (this is tested):
select ind
from tmp1 t1
where val > (select val from jdoyle.tmp1 t2 where t2.ind = t1.ind-1)
and val > (select val from jdoyle.tmp1 t2 where t2.ind = t1.ind+1);
Doing this with a single loop in PHP is likely to be much faster than shoehorning this into an SQL query, but if you really want to you could self-join the table with itself with something like:
SELECT b.index
FROM points AS a, points AS b, points AS c
WHERE a.index = b.index-1 AND c.index = b.index+1
AND a.value < b.value AND c.value < b.value
(Untested, so *cross fingers*.)
You could write your loop inside a stored procedure in SQL if your SQL database supports stored procedures. However, I don't think sqlite has rich enough stored procedures to do something like this, you would need to use mysql, postgresql or similar.
Well, if you're using sqlite on production I imagine that you don't have a huge bunch of data. Considering this, the best solution really is to solve it at php level.

Categories