Table A results based on distance to point in table B - postgis

I have 2 tables, locations and zipcodes.
Both the locations and zipcodes tables have a single point geometry.
I wrote a query that I can pass string values for lng,lat to, but I'd like to the same thing by only passing in a zipcode, which is what the distance results would be based off of.
SELECT *, ST_distance(geometry::geography, ST_PointFromText('POINT(-118.0754445 32.4836479)', 4326)::geography) as dist
FROM locations
WHERE st_dwithin(geometry, ST_PointFromText('POINT(-118.0754445 32.4836479)', 4326)::geography, 1609)
ORDER BY dist;

Put both tables in the FROM clause (assign them a alias) and add a where condition with the zipcode you need:
SELECT *, ST_distance(l.geometry::geography, zc.geometry::geography ) as dist
FROM locations AS l, zipcodes AS zc
WHERE st_dwithin(l.geometry, zc.geometry::geography), 1609) AND
zc.code = 11111
ORDER BY dist;

Related

SQL Server Polygon format

SELECT TOP 1 KMLLocation FROM Polygon
Result: 0xE61000000104210000004ACE893DB4BF19403EB2B96A9EFF534082919735B1C0194039807EDFBFFF534052F17F4754C81940976F7D586F0054405AD76839D0D31940AED3484BE50054409E961FB8CAD3194087BF266BD40054403F90BC7328D3194071C806D2C5005440844A5CC7B8D21940E4D70FB1C100544014CE6E2D93D1194062BF27D6A90054404FB2D5E594D01940E27668588C005440E910381268D01940E7E26F7B820054409AEAC9FCA3CF1940A54E4013610054409432A9A10DD01940CD902A8A5700544015E126A3CAD01940FE0E45813E0054407FBDC282FBD11940C30DF8FC30005440EB1B98DC28D2194038312427130054403065E08096CE19404A7CEE04FBFF534082035ABA82CD1940C2F7FE06EDFF5340462234828DCB19409373620FEDFF534031B2648EE5CD1940E338F06AB9FF5340CFDC43C2F7CE1940321EA5129EFF5340B98C9B1A68CE194055A3570394FF5340A8E15B5837CE1940639CBF0985FF53403868AF3E1ECA1940001FBC7669FF534029CB10C7BAC81940ED9C668176FF5340C6DB4AAFCDC61940AD18AE0E80FF534047CCECF318C51940F390291F82FF5340EDB776A224C41940FD851E317AFF5340E4F90CA837C31940C440D7BE80FF5340DF1AD82AC1C21940462234828DFF53409C69C2F693C1194007D2C5A695FF5340C5387F130AC119406AFB57569AFF5340D1E7A38CB8C01940574277499CFF53404ACE893DB4BF19403EB2B96A9EFF534001000000020000000001000000FFFFFFFF0000000003
SELECT TOP 1 KMLLocation .ToString() FROM Polygon
Result:
POLYGON ((79.994044 6.437211, 79.996086 6.438176, 80.006796 6.445634, 80.013995 6.456849...
Expected Result:
POLYGON ((6.437211 79.994044, 6.438176 79.996086, 6.445634 80.006796, 6.456849, 80.013995...
How do I swap Lat and Long from geography polygon?
Here's what I came up with:
DECLARE #g GEOGRAPHY = /* your hex representation from above */
#new VARCHAR(MAX);
WITH points AS (
SELECT #g.STPointN(n.n) AS p, n
FROM tempdb.dbo.Numbers AS n
WHERE n <= #g.STNumPoints()
)
SELECT #new = CONCAT('POLYGON((', (
SELECT STRING_AGG(CONCAT(p.Lat, ' ', p.Long), ',') WITHIN GROUP (ORDER BY p.n)
FROM points AS p
), '))')
SELECT geography::STGeomFromText(#new, #g.STSrid).ReorientObject();
It's pretty straightforward. I'm creating a common table expression (CTE) to decompose the existing polygon into its constituent corners using a numbers (or tally) table. All that is is a table with one column with integers from 1 to some large number. It's helpful for cases like this. From there, I'm swapping the latitude and longitude of the points and then re-assembling them into the WKT for the polygon. Lastly, I'm creating an actual geography instance from the WKT. Note - I'm calling ReorientObject() as the new polygon appears to suffer from a ring orientation problem insofar as it defined the whole globe with a small hole in it (the shape of your polygon).

Trying to find distance between two sets of Lat-longs

I have a dataset that has a 100,000+ addresses, and each of the addresses have two sets of Latitude and Longitude (basically x_lat, x_lon, y_lat, y_lon) on MSSQL. The lat-longs are for the same address but from two different sources, and I am trying to find the difference in distance between the two. I've done some research, and am trying to use the code below (from AakashM on Stackoverflow) but I'm getting an error saying that the subquery returned more than 1 value, which is not permitted.
DECLARE #orig_lat DECIMAL(12, 9)
DECLARE #orig_lng DECIMAL(12, 9)
SET #orig_lat=(SELECT x_lat FROM #Distance) SET #orig_lng= (SELECT x_lon FROM #Distance)
DECLARE #orig geography = geography::Point(#orig_lat, #orig_lng, 4326);
SELECT *,
#orig.STDistance(geography::Point(y_Lat, y_Lon, 4326))
AS distance
--INTO #includeDistances
FROM #Distance
The error makes sense because the #orig_lat and #orig_lon need to be set to a specific lat-long, but is there a way I can set it to the column instead so I can get the distance for each of the addresses, without having to manually input the lat-longs? I've included an image of the first two rows of the #Distance dataset below:
enter image description here
If I understand you correctly, you're try to calculate the distinct between x and y lat/lng's.
Example
SELECT *
,Distance = geography::Point(x_Lat, x_Lon, 4326).STDistance(geography::Point(y_Lat, y_Lon, 4326))
From YourTable
Where x_lat<>y_lat
or x_lon<>y_lon
There WHERE is optional.

Weighted Average w/ Array Formula & Query That Pulls From A Separate Sheet

Link To Sheet
So I've got an array formula which I've included below. I need to adjust this so that it becomes a weighted average based on variables stored on a sheet titled Variables.
Current Formula:
=ARRAYFORMULA(QUERY(
{PROPER(ADP!A3:A),ADP!E3:S;
PROPER(ADP!J3:J),ADP!S3:S;
PROPER(ADP!Z3:Z),ADP!AG3:AG},
"select Col1, Sum(Col2)
where
Col2 is not null and
Col1 is not null
group by Col1
order by Sum(Col2)
label
Col1 'PLAYER',
Sum(Col2) 'ADP AVG'"))
Here's what I thought would work but doesn't:
=ARRAYFORMULA(QUERY(
{PROPER(ADP!A3:A),ADP!E3:E*(Variables!$F$11/Variables!$F$14);
PROPER(ADP!J3:J),ADP!S3:S*(Variables!$F$12/Variables!$F$14);
PROPER(ADP!Z3:Z),ADP!AG3:AG*(Variables!$F$13/Variables!$F$14)},
"select Col1, Sum(Col2)
where
Col2 is not null and
Col1 is not null
group by Col1
order by Sum(Col2)
label
Col1 'PLAYER',
Sum(Col2) 'ADP AVG'"))
What I'm trying to get is the value pulled in K to be multiplied by the value in VariablesF11, the value pulled in Y to be multiplied by VariablesF12, and the value in AL multiplied by the variables in F13. And have that numerator divided by the value in VariablesF14.
After our extensive chat, I'm providing here the answer we came up with, just on the chance it might somehow help someone else. But the issue in your case was less about the technicalities of the formula, and more about the structuring of multiple data sources, and the associated logic to pull the data together.
Here is the main formula:
={"Adjusted
Ranking
by " & Variables!F21;
arrayformula(
if(A2:A<>"",
( if(((D2:D>0) * Source1Used),D2:D,Variables!$F$21)*Variables!$F$12
+ if(((F2:F>0) * Source2Used),F2:F,Variables!$F$21)*Variables!$F$13
+ if(((H2:H>0) * Source3Used),H2:H,Variables!$F$21)*Variables!$F$14
+ if(((J2:J>0) * Source4Used),J2:J,Variables!$F$21)*Variables!$F$15
+ if(((L2:L>0) * Source5Used),L2:L,Variables!$F$21)*Variables!$F$16
+ if(((N2:N>0) * Source6Used),N2:N,Variables!$F$21)*Variables!$F$17 )) / Variables!$F$18) }
A2:A is the list of players' names. The D2:D>0 is a test of whether that player has a rating obtained from a particular data source.
Source1Used is a named range for a tickbox cell, where the user can indicate whether that data source is to be included in the calculations.
This formula creates an average value, using from 1 to 6 possible sources, user selectable.
The formula that gave the rating value for one specific source is as follows:
={"Rating in
Source1";ArrayFormula(if(A2:A<>"",if(C2:C,vlookup(A2:A,indirect("ADP!$" & ADP!E3 & "$10:" & ADP!E5),ADP!E6-ADP!E4+1,0),0),""))}
This takes a name in column A, checks if it is listed in a specific source's data, and if so, it pulls back the rating value from the data source. INDIRECT is used since the column locations for each data source may vary, but are obtained from a fixed table, in cells ADP!E3 and E5. E4 and E6 are the numeric values of the column letters.

How to get the distance between points in my geom and entry point longitude and latitude

everyone, I have table name 'geom' and I would like to calculate the distance between points that exist in my table like 0101000020730800001DAB949EE95D4040E124CD1FD3F04340
and entry points longitude and latitude and I tried this
SELECT *
FROM postgis.cafeecoor
WHERE ST_Distance_Sphere(geom, ST_MakePoint(32.733792,39.865589)) <= 1 * 1609.34
You can use the geography datatype that returns distances in meters.
SELECT *, st_distance(geom::geography, ST_MakePoint(32.733792,39.865589)::geography)
FROM postgis.cafeecoor
For your example, it returns 1760.32533367 meters.
Depending how your geometry is saved (as a true geometry or as text, with or without a set projection), you might have to add a few extra steps, like creating the geometry and setting its coordinate system
SELECT *, st_distance(
st_setsrid(geom::geometry,4326)::geography,
ST_MakePoint(32.733792,39.865589)::geography)
FROM postgis.cafeecoor;

Selecting Nodes Separating Line Segments

I want to select nodes separating line segments in a layer. I want to select nodes only where they are intersected by two lines, NOT when they meet with more than two line (e.g. a T intersection or four way intersection, etc.).
Here's the best picture I can give (I dont have the reputation to post pictures). The --- line on the left is the first segment and the --x--x--x line on the right the second. The O is the node in the middle I want to select.
--------------------------------------0--x---x--x---x---x---x--x--x--x--x--x--x--x
I do NOT want to select nodes where more than two lines touch the node.
So far I have tried this query
CREATE TABLE contacts_st_touching_faults as
SELECT ST_Intersection(a.the_geom, b.the_geom), Count(Distinct a.gid) = 2
FROM final_layer as a, final_layer as b
WHERE ST_Touches(a.the_geom, b.the_geom)
AND a.gid != b.gid
GROUP BY ST_Intersection(a.the_geom, b.the_geom)
When I run this query it gives me intersections with more than two lines intersecting (T intersections and 4 way intersections).
I have also tried subing ST_intersects in and that didn't seem to work as well as ST_touches, but if you know how to make them work or any other method, it would be much appreciated!
Thanks for the help!
This should work:
WITH contacts AS(
SELECT a.gid AS gid1,b.gid AS gid2, ST_Intersection(a.the_geom, b.the_geom) AS intersection
FROM final_layer as a, final_layer as b
WHERE ST_Touches(a.the_geom, b.the_geom)
AND a.gid<b.gid
)
SELECT *
FROM contacts c1
LEFT JOIN contacts c2
ON ((c1.gid1=c2.gid1 AND c1.gid2<>c2.gid2) OR (c1.gid1=c2.gid2 AND c1.gid1<>c1.gid2))
AND c1.intersection=c2.intersection
WHERE c2.gid1 IS NULL;
It will perform better if ST_Intersection is moved to the final query but I wanted to make it simple.
This will list nodes with tow lines intersecting.
SELECT array_agg(gid) AS gids, count(gid) AS count, geom
FROM
-- lists all vertices (points) from lines
(SELECT gid, (ST_DumpPoints(geom)).geom AS geom
FROM lines_layer) AS p
GROUP BY p.geom
HAVING count(gid) = 2
ORDER BY count(gid);
For all nodes, replace '= 2' with '> 1'

Resources