PostGIS Intersection multiple geometry - postgis

I have a postgis polygon table (zipcode1) and two point table (pm253, blockpop). I would like to intersect the polygon table against the two point table and count how many point I have for each point table, sum up some other attributes to calculate a ratio. I am able to do it against a single table as you see here:
SELECT zipcode1.gid, count(*) as totpm, sum(pm) as totsum, sum(pm)/count(*) as res
FROM pm253, zipcode1
WHERE st_intersects(st_buffer(zipcode1.geom, 100),pm253.geom)
GROUP BY zipcode1.gid
Any suggestions? Thank you.

Try union;
SELECT 'zipcode1<->pm253' as tables, zipcode1.gid, count(*) as totpm, sum(pm) as totsum, sum(pm)/count(*) as res
FROM pm253, zipcode1
WHERE st_intersects(st_buffer(zipcode1.geom, 100),pm253.geom) and zipcode1.geom&&pm253.geom -- to accelerate query
GROUP BY zipcode1.gid
union
SELECT 'zipcode1<->blockpop' as tables, zipcode1.gid, count(*) as totpm, sum(pm) as totsum, sum(pm)/count(*) as res
FROM blockpop, zipcode1
WHERE st_intersects(st_buffer(zipcode1.geom, 100),blockpop.geom) and zipcode1.geom && blockpop.geom -- to accelerate query
GROUP BY zipcode1.gid

Related

Error when joining a polygon table to a point table based on point being within a given polygon

The overall goal that I am attempting to achieve is to join two tables together based on a point (created from xy coordinates in feet) from one table falling within a polygon from another table. The expected result is given records and the name of the polygon it falls within. When the query is executed, the below error is returned, in summary:
A .NET Framework error occurred during execution of user-defined routine or aggregate "geometry":
System.FormatException: 24114: The label 395 in the input well-known text (WKT) is not valid.<
Due to not being familiar with geometry data in SQL, I am not fully certain whether I am even on the right path, so any advice would be appreciated.
The polygon table that I am attempting to join is a temporary table and the polygons are formatted as geometry. Running the below code in isolation executes as expected by creating a spatial output.
My apologies, it appears code formatting is not working on my phone and my work computer’s browser is not supported.
DECLARE #Hex1 TABLE (PolyGeom geometry, Hex varchar(6))
INSERT INTO #Hex1
Values
(geometry::STPolyFromText('Polygon((7598795.05553838 734372.656,7598217.70526919 735372.656,7597063.00473081 735372.656,7596485.65446162 734372.656,7597063.00473081 733372.656,7598217.70526919 733372.656,7598795.05553838 734372.656))',0),1),
(geometry::STPolyFromText('Polygon((7602259.15715352 734372.656,7601681.80688433 735372.656,7600527.10634595 735372.656,7599949.75607676 734372.656,7600527.10634595 733372.656,7601681.80688433 733372.656,7602259.15715352 734372.656))',0),2),
(geometry::STPolyFromText('Polygon((7605723.25876865 734372.656,7605145.90849947 735372.656,7603991.20796109 735372.656,7603413.8576919 734372.656,7603991.20796109 733372.656,7605145.90849947 733372.656,7605723.25876865 734372.656))',0),3)’’’
The table that the polygon table is joined to does not have points so have created a table that has a field with the calculated points. Running the below code in isolation works as expected by returning records with a point.
INSERT INTO #Points (Primary_Key, geom)
select a.rID, geometry::STGeomFromText('POINT('+convert(varchar(20),a.x_coordinate)+' '+convert(varchar(20),a.y_coordinate)+')',0) as geom
from data_a a'''
The tables are joined as shown below
WITH CTE1 AS --Due the number of polygons exceeding insert limits, multiple tables are created and unioned in a CTE
( Select*
From #Hex1
UNION ALL
Select*
From #Hex2
UNION ALL
Select*
From #Hex3
UNION ALL
Select*
From #Hex4)
select a.rID, C.Hex
from data_a a --Existing table with x y coordinates
left join #points p --Joins the point created in points table to the same case in go_data
on a.rID = p.Primary_key
left join CTE1 C --Joins the hexagon to the point if hex containts the point
on p.geom.STIntersects (c.hex) =1'''
Below is the full code, with the number of polygons in each table trimmed down
IF OBJECT_ID('tempdb..#Points') IS NOT NULL DROP TABLE #Points
create table #Points (Primary_key numeric identity not null, geom geometry)
SET IDENTITY_INSERT #Points ON
INSERT INTO #Points (Primary_Key, geom)
select g.rin, geometry::STGeomFromText('POINT('+convert(varchar(20),a.x_coordinate)+' '+convert(varchar(20),a.y_coordinate)+')',0) as geom
from data_a a
;
DECLARE #Hex1 TABLE
(PolyGeom geometry, Hex varchar(6))
INSERT INTO #Hex1
Values
(geometry::STPolyFromText('Polygon((7598795.05553838 734372.656,7598217.70526919 735372.656,7597063.00473081 735372.656,7596485.65446162 734372.656,7597063.00473081 733372.656,7598217.70526919 733372.656,7598795.05553838 734372.656))',0),1),
(geometry::STPolyFromText('Polygon((7602259.15715352 734372.656,7601681.80688433 735372.656,7600527.10634595 735372.656,7599949.75607676 734372.656,7600527.10634595 733372.656,7601681.80688433 733372.656,7602259.15715352 734372.656))',0),2),
(geometry::STPolyFromText('Polygon((7605723.25876865 734372.656,7605145.90849947 735372.656,7603991.20796109 735372.656,7603413.8576919 734372.656,7603991.20796109 733372.656,7605145.90849947 733372.656,7605723.25876865 734372.656))',0),3)
DECLARE #Hex2 TABLE
(PolyGeom geometry, Hex varchar(6))
INSERT INTO #Hex2
Values
(geometry::STPolyFromText('Polygon((7680201.44349411 721372.656,7679624.09322492 722372.656,7678469.39268654 722372.656,7677892.04241735 721372.656,7678469.39268654 720372.656,7679624.09322492 720372.656,7680201.44349411 721372.656))',0),1000),
(geometry::STPolyFromText('Polygon((7683665.54510925 721372.656,7683088.19484006 722372.656,7681933.49430168 722372.656,7681356.14403249 721372.656,7681933.49430168 720372.656,7683088.19484006 720372.656,7683665.54510925 721372.656))',0),1001),
(geometry::STPolyFromText('Polygon((7687129.64672438 721372.656,7686552.29645519 722372.656,7685397.59591681 722372.656,7684820.24564763 721372.656,7685397.59591681 720372.656,7686552.29645519 720372.656,7687129.64672438 721372.656))',0),1002)
DECLARE #Hex3 TABLE
(PolyGeom geometry, Hex varchar(6))
INSERT INTO #Hex3
Values
(geometry::STPolyFromText('Polygon((7765071.93306498 708372.656,7764494.58279579 709372.656,7763339.88225741 709372.656,7762762.53198822 708372.656,7763339.88225741 707372.656,7764494.58279579 707372.656,7765071.93306498 708372.656))',0),1999),
(geometry::STPolyFromText('Polygon((7768536.03468011 708372.656,7767958.68441092 709372.656,7766803.98387254 709372.656,7766226.63360335 708372.656,7766803.98387254 707372.656,7767958.68441092 707372.656,7768536.03468011 708372.656))',0),2000),
(geometry::STPolyFromText('Polygon((7772000.13629525 708372.656,7771422.78602606 709372.656,7770268.08548768 709372.656,7769690.73521849 708372.656,7770268.08548768 707372.656,7771422.78602606 707372.656,7772000.13629525 708372.656))',0),2001)
WITH CTE1 AS
( Select*
From #Hex1
UNION ALL
Select*
From #Hex2
UNION ALL
Select*
From #Hex3)
select a.rID, C.Hex
from data_a a
left join #points p --Joins the point created in points table to the same case in go_data
on g.rin = p.Primary_key
left join CTE1 C --Joins the hexagon to the point if hex containts the point
on p.geom.STIntersects (c.hex) =1
isn't it just a typo? you should intersect the point geometry with the geometry of the polygon and not the hex column.
left join CTE1 C --Joins the hexagon to the point if hex containts the point
on p.geom.STIntersects (c.PolyGeom) =1

Adapting Amazon-Redshift query computing average to query creating list of elements

I am not very familiar with the syntax of Amazon Redshift so my co-worker helped me write a query to compute the average of a column of numbers. I am not very familiar with the syntax and I want to adapt it to create a list containing all the numbers instead.
The list I want to create is a list of elements that is embedded in joins which makes the operation more complicated. The query that my coworker helped me write is the following:
''' --- Query written with co-worker's help
SELECT LOWER(some_query_query) as query,
AVG(n_results::FLOAT)::FLOAT as
n_results_avg,
count(*) as data_count
from some_field
JOIN
(SELECT
request_id,
some_id,
count(*) as n_results
from s_results
WHERE type_name = 'tinder_match'
AND time <= '2019-06-20'
AND time >= '2019-06-19'
GROUP BY request_id, some_id) as n_count
ON n_count.request_id = some_field.request_id
WHERE time <= '2019-06-20'
AND time >= '2019-06-19'
AND language = 'en'
AND country = 'US'
GROUP BY LOWER(some_query_query)
ORDER BY n_results_avg DESC
--- Current Behaviour: Returns a table with query,
n_results_avg, data_count as columns
--- Desired Behaviour: Returns a table with query,
list_of_name_match_results, data_count as columns
--- list_of_name_match_results is a list containing all name
match results (numbers)
'''
Actual results: Output table with query, name_match_results_avg, data_count as columns
Desired results: Output table with query, list_of_name_match_results, data_count as columns

Get random data from SQL Server without performance impact

I need to select random rows from my sql table, when search this cases in google, they suggested to ORDER BY NEWID() but it reduces the performance. Since my table has more than 2'000'000 rows of data, this solution does not suit me.
I tried this code to get random data :
SELECT TOP 10 *
FROM Table1
WHERE (ABS(CAST((BINARY_CHECKSUM(*) * RAND()) AS INT)) % 100) < 10
It also drops performance sometimes.
Could you please suggest good solution for getting random data from my table, I need minimum rows from that tables like 30 rows for each request. I tried TableSAMPLE to get the data, but it returns nothing once I added my where condition because it return the data by the basis of page not basis of row.
Try to calc the random ids before to filter your big table.
since your key is not identity, you need to number records and this will affect performances..
Pay attention, I have used distinct clause to be sure to get different numbers
EDIT: I have modified the query to use an arbitrary filter on your big table
declare #n int = 30
;with
t as (
-- EXTRACT DATA AND NUMBER ROWS
select *, ROW_NUMBER() over (order by YourPrimaryKey) n
from YourBigTable t
-- SOME FILTER
WHERE 1=1 /* <-- PUT HERE YOUR COMPLEX FILTER LOGIC */
),
r as (
-- RANDOM NUMBERS BETWEEN 1 AND COUNT(*) OF FILTERED TABLE
select distinct top (#n) abs(CHECKSUM(NEWID()) % n)+1 rnd
from sysobjects s
cross join (SELECT MAX(n) n FROM t) t
)
select t.*
from t
join r on r.rnd = t.n
If your uniqueidentifier key is a random GUID (not generated with NEWSEQUENTIALID() or UuidCreateSequential), you can use the method below. This will use the clustered primary key index without sorting all rows.
SELECT t1.*
FROM (VALUES(
NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID())
,(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID())
,(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID()),(NEWID())) AS ThirtyKeys(ID)
CROSS APPLY(SELECT TOP (1) * FROM dbo.Table1 WHERE ID >= ThirtyKeys.ID) AS t1;

SQL Spatial number of times a Linestring intersects other Linestrings

So, I have a table named "lines" that has a field named "WKT" with the corresponding geography.
I builded a query that gives me the name of the line that was intersected, like this:
DECLARE #DF GEOGRAPHY
Set #DF=GEOGRAPHY::STLineFromText('LINESTRING(-9.564498 52.237100,-9.564906 52.243924,-9.565699 52.245563,-9.568173 52.251014,-9.567142 52.257567,-9.564291 52.262366,-9.563453 52.262972,-9.563447 52.262980,-9.563447 52.262980,-9.563447 52.262980)', 4326)
select name, #DF.STIntersects(WKT) AS inters
from lines WHERE #DF.STIntersects(WKT)=1
And it works very well. The problematic case is when this #DF line is a "go and return by the same path". In this case I wanted to know the names of the repeated lines that were intersected.
Is this possible to do?
Sure. Assuming that you've got a tally table (i.e. a table with numbers 1 through some large number):
DECLARE #DF GEOGRAPHY
Set #DF=GEOGRAPHY::STLineFromText('LINESTRING(-9.564498 52.237100,-9.564906 52.243924,-9.565699 52.245563,-9.568173 52.251014,-9.567142 52.257567,-9.564291 52.262366,-9.563453 52.262972,-9.563447 52.262980,-9.563447 52.262980,-9.563447 52.262980)', 4326)
WITH cte AS (
SELECT n, #DF.STCurveN(n) AS curve
FROM dbo.Numbers
WHERE n <= #DF.STNumCurves()
)
select name, #DF.STIntersects(WKT) AS inters
from lines AS l
JOIN cte AS c
ON l.WKT.STIntersects(c.curve) = 1
I'm sure that you could get away without using the CTE, but that was what made the most sense in my head.

Substract 2 columns from postgreSQL LEFT JOIN query with NULL values

I have a postgreSQL query which should be the actual stock of samples on our lab.
The initial samples are taken from a table (tblStudies), but then there are 2 tables to look for to decrease the amount of samples.
So I made a union query for those 2 tables, and then matched the uniun query with the tblStudies to calculate the actual stock.
But the union query only gives values when there is a decrease in samples.
So when the study still has it's initial samples, the value isn't returned.
I figured out I should use a JOIN operation, but then I have NULL values for my study with initial samples.
Here is how far I got, any help please?
SELECT
"tblStudies"."Studie_ID", "SamplesWeggezet", c."Stalen_gebruikt", "SamplesWeggezet" - c."Stalen_gebruikt" as "Stock"
FROM
"Stability"."tblStudies"
LEFT JOIN
(
SELECT b."Studie_ID",sum(b."Stalen_gebruikt") as "Stalen_gebruikt"
FROM (
SELECT "tblAnalyses"."Studie_ID", sum("tblAnalyses"."Aant_stalen_gebruikt") AS "Stalen_gebruikt"
FROM "Stability"."tblAnalyses"
GROUP BY "tblAnalyses"."Studie_ID"
UNION
SELECT "tblStalenUitKamer"."Studie_ID", sum("tblStalenUitKamer".aant_stalen) AS "stalen_gebruikt"
FROM "Stability"."tblStalenUitKamer"
GROUP BY "tblStalenUitKamer"."Studie_ID"
) b
GROUP BY b."Studie_ID"
) c ON "tblStudies"."Studie_ID" = c."Studie_ID"
Because you're doing a LEFT JOIN to the inline query "C" some values of c."stalen_gebruikt" can be null. And any number - null is going to yield null. To address this we can use coalesce
So change
"samplesweggezet" - c."stalen_gebruikt" AS "Stock
to
"samplesweggezet" - COALESCE(c."stalen_gebruikt",0) AS "Stock

Resources