Query with negative numbers not working as expected - socrata

I'm trying to write a query to this data set:
https://data.sfgov.org/City-Infrastructure/Street-Tree-List/tkzw-k3nq
I want to return the records that have a latitude AND longitude between certain values.
My attempt at a query string:
"https://data.sfgov.org/resource/2zah-tuvt.json?$limit=1000&$where=latitude between 37.709864 and 37.781918 AND longitude between -122.398942 and -122.501212"
The request limits the response to 1000 records and searches for records with a latitude between the specified numbers AND a longitude between the specified numbers.
The request does not produce an error but it also doesn't include any results. There are thousands of records that should satisfy the parameters and I'm not sure why I'm not getting a response.
When I test off of the latitude values only, the response returns as expected. When I test off of the longitude values only, I get no response. I've tested the longitude for values < 0 (since all of the longitude values are negative numbers) and that does produce a correct response.
I have a feeling the negative numbers I'm trying to search for are causing the issue. Is there some way to format the negative numbers so SoQL sees them as part of the search number instead of an operator? I've also tried wrapping the negative numbers in parentheses but that didn't help.
What do I need to change to get the response to return my desired results?

On a "between", the LOWER number needs to be on the left and the GREATER number on the right. Negative numbers obviously work the opposite (greatest absolute value actually belongs on the LEFT)
change to
between -122.501212 and -122.398942

Related

Find Row Where Sum is Reached from Single Joined Column (not a range of cells)

I'm trying to run a formula to identify in which row a total sum is reached.
I've been able to do that calculation when I have an entire range of cells to work with, however, I'm doing a filter / join calculation because I need to do this from an individual row with all the data instead of an entire range of cells.
Here is an example google sheet (EDITABLE - feel free) where you can see the range and working formula (both below). Help getting this from the single-cell versions on the top would be very helpful. The error I get with both row() & index() formulas is that the "argument must be a range".
If there's another way to do this besides the single-cell I had that doesn't require referencing the range (e.g. using FILTER) then I'm open to it.
My desired result is to be able to pull the get the second column (date) at the point when the sum is reached (can be via the INDEX & MATCH formula I used or an alternative). This will tell me the earliest date that feeds into the desired sum.
Yes unfortunately you can't do that trick with SUMIFS to get a running total unless the column being totalled is an actual range.
The only approach I know is to multiply successive values by a triangular array like this:
1 0 0 ...
1 1 0 ...
1 1 1 ...
so you get just the sum of the first value, the first 2 values, then 3 values up to n.
This is the formula in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,","))))>=
COLUMN(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,",")))),1,0),TRANSPOSE(SPLIT(A5,",")))))
And the formula in F6 is just
=to_date(INDEX(TRANSPOSE(SPLIT(B5,",")),F5,1))
EDIT
You might have guessed that the above formula was adapted from Excel, where you try to avoid volatile functions like Offset and Indirect.
I have realised since posting this answer that it could be improved in two ways:
(1) By using Offset or Indirect, thus avoiding the need to define a range of arbitrary size like A1:ALL1000
(2) By implying a 2D array by comparing a row and column vector, rather than actually defining a 2D array. This would give you something like this in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:"&address(COUNT(split(A5,",")),1)))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))
which could be further simplified to:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:A"&COUNT(split(A5,","))))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))

Spatialite find the nearest node for the given lat/lon

I am struggle on this for a few days, I am not sure why the query was wrong..
I want to find the nearest point at the given lat/lon.
SELECT rid,DISTANCE(geometry, MakePoint(-79.91759, 43.266571))
FROM room2f ORDER BY DISTANCE(Startpoint(geometry), MakePoint(-79.91759, 43.266571))limit 1
It's always return the first row, nomatter what point I use. Then I tried to remove "limit1":
SELECT rid,DISTANCE(geometry, MakePoint(-79.91759, 43.266571))
FROM room2f ORDER BY DISTANCE(Startpoint(geometry), MakePoint(-79.91759, 43.266571))
The result is very strange... The result is sorted by rid rather than distance, I think this is why it always return the first row. Is my query wrong? Or, there is a bug in Spatialite?
Thanks]1
In your sql statement you compare to different distances..
From your geometry in general to your specific point (as I know it is the shortest distance from the point to your geometry).
From the first point of your geometry to your specific point.
Therefore you also get a different ordering of your result!
See the reference to the distance function:
http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.2.0.html#p13

Radius Query with vender radius restrictions

I have the following radius query below. The first select will get me every record within 4 miles. (just to keep things simple, the zip in this example is just a primary key and should not be thought of as an actual zip. I'm just trying to model this as a vendor within a given long/lat.)
5 records are returned within 4 miles of latitude 43 and longitude- -74.37
What I'm looking to do is once the records are found, then do a reverse select on the records found using the restriction column as my new radius restriction to eliminate records where vendors do not want to be found outside a particular distance from their physical location.
In my query example below, I'm expecting to find all results except fonda 12068 because that record although is within 4 miles of the first select only wants to be visible within 1 mile (restriction column) of his physical location. The image however is the actual results produced. Can someone help me to understand what I'm doing wrong?
My thought was I could use the the long/lat along with the restriction from the result of the first query to see if a zip was returned matching the original zip.
SELECT zip1.* FROM zip_detail as zip1
WHERE (3958*3.1415926*sqrt((latitude-43)*(latitude-43)
+ cos(latitude/57.29578)*cos(43/57.29578)
*(longitude- -74.37)*(longitude- -74.37))/180)
<= 4
and zip1.zip in (SELECT zip2.zip FROM zip_detail as zip2
WHERE (3958*3.1415926*sqrt((latitude-zip1.latitude)*(latitude-zip1.latitude)
+ cos(latitude/57.29578)*cos(zip1.latitude/57.29578)
*(longitude- zip1.longitude)*(longitude- zip1.longitude))/180)
<= zip1.restriction)
I created a sqlfiddle example

Odd results in MS Access Query using a DSUM function and parameters

I've just started using MS Access this month and I have a very odd bug. I'm trying to create a query that searches for records in a table that have a maxBenefit (a dsum from a different table's field, with a one to many relationship) within a certain range. I'm using the DSUM function to get the maxBenefit because the table has a dailyBenefits field that need to be added together.
Here is my function:
maxBenefitOfQuote: Nz(DSum("[wholeYearBenefit]","tblDisabilityQuoteDailyBenefits",
"[quoteID] = " & [tblDisabilityQuotes].[ID]))
I know the function works because it produces the correct values. The query also takes in two parameters from a form to create a range for maxBenefits.
I limit the results with this criteria:
>=[Forms]![frmDisabilityFindSimilarQuotes]![minBenefitTotal] And
<=[Forms]![frmDisabilityFindSimilarQuotes]![maxBenefitTotal]
The problem is I get very odd results from the query with maxBenefits outside the range or not returning records with maxBenefits inside the range. If I set the minBenefitTotal to 0 and the max BenefitTotal to 100000000 I get no records returned from the query. If I set the minBenefitTotal to 0 and the maxBenefitTotal to 999999999 I get all the proper records.
Any ideas why this is happening? Thanks in advanced.
First,
Try wrapping both of your inputs in a call to CCur:
>=CCur([Forms]![frmDisabilityFindSimilarQuotes]![minBenefitTotal]) And
<=CCur([Forms]![frmDisabilityFindSimilarQuotes]![maxBenefitTotal])
Next,
If you omit the actual form inputs, and hard-code numbers into the criteria, does it work?
For Example: (>= 0 and <= 100000000)
If that worked... It feels like a string -> number conversion issue. Make sure all string input is actually a number (via CCur()) before sending it into the query.

Paging Results: Handling invalid passed data

Have a simple page that pulls results from MySQL and displays them in a table. I have enabled paging on the results, and allowed the user to set the number of results being displayed per page. I am passing two querystring values to handle this: 'page' and 'count'.
I am then taking these values to calculate the LIMIT's of my MySQL query, using the SQL_CALC_FOUND_ROWS directive and following that with a call to SELECT FOUND_ROWS(); to get the total number of results. This all works nicely.
Now, I want to validate the querystring values. As I am storing the possible "correct" values for the results/page value of 'count' in an array, I simply check that the passed 'count' value is in that array, and if not set it to the default value. For the 'page' value, I am having a bit of a mental block... in order to determine if there are any results for the passed 'page', meaning it is "correct", I need to go to the database and find the result count first, but since I only want to go to the db once, I need to include the LIMIT's, which are based on the passed 'page' value... chicken and egg. I have a couple thoughts on how to solve this:
Run the query as coded above, and if the (('page' - 1) * 'count') result is greater than the value returned from SELECT FOUND_ROWS();, re-run the query with new LIMIT's set to 0, count.
Get the full result set, verify that the passed page is correct, then do another pull from the database with the LIMIT values.
I'd rather not go back to the database at all, but as I mentioned, having a mental block on this rather common issue.
Thanks,
Paul
I ended up using the first solution above -
Run the query as coded above, and if the (('page' - 1) * 'count') result is greater than the value returned from SELECT FOUND_ROWS();, re-run the query with new LIMIT's set to 0, count.
It's not perfect in that a second database pull is required for cases where the passed page value is bad, but given that is an unexpected case only triggered by the intentional passage of bad data on the part of the user, it's acceptable. If anyone else has a better solution, I'd be happy to re-open the question.