How to put together two queries? - postgresql

In the title is what I need.
CREATE TABLE newTable1 AS SELECT t2.name,t2.the_geom2
FROM t1,t2
WHERE ST_Contains(ST_Expand(t2.the_geom2,0.05),t1.the_geom1)
and t1.gid=2;
CREATE TABLE newTable2 AS SELECT t1.the_geom,t1.label FROM t1 WHERE t1.gid=2;
First query result is all points within polygon and apart from it for 5min where this polygon has gid=2. But I also want to display this polygon. I tried to write in first query
... AS SELECT t2.name,t2.the_geom2,t1.the_geom1,t1.label ...but got only points without polygon...
This question is linked with already asked question "How to find all points away from some polygon?". But didn't get answere, so please...
And is ST_expand ok solution or it will be better to use ST_DWithin or ST_buffer ?

You can't combine two CREATE TABLE statements into one. Why are you creating tables if you are just querying data?
It sounds like what you are really trying to do is one query that will give you the points within the polygon and the polygon itself. Something like this?
SELECT
t1.the_geom AS polygon, t1.label AS polygon_label,
t2.the_geom2 AS point, t2.name AS point_name
FROM
t1, t2
WHERE
ST_Contains(ST_Expand(t2.the_geom2,0.05), t1.the_geom1)
AND t1.gid = 2;
If this is still not clear, post your complete table definitions and more details about what you are trying to do.

Related

Use Query result as element of another query

I have this two queries,
SELECT ST_AsText(geom)
FROM areasTable
WHERE "Name" ILIKE 'Kachina';
Let's say that it returns a polygon value of: POLYGON((-XXX.XX XX.XXX, -XXX.XX XX.XXX, -XXX.XX XX.XXX, -XXX.XX XX.XXX)). I then use that value to do another search.
SELECT "ROAD_NAME"
FROM addresses
WHERE ST_Contains(ST_GEOMFROMTEXT('POLYGON((-XXX.XX XX.XXX, -XXX.XX XX.XXX, -XXX.XX XX.XXX, -XXX.XX XX.XXX))',4326), addresses.geom);
What I have been trying to do is save a step and just find all the roads within a certain area without having to manually copy and paste the polygon of the area. Any ideas?
Try creating a stored procedure. https://www.w3schools.com/sql/sql_stored_procedures.asp
Then write a program in a language that can interact with the SQL DB and run a loop that calls this stored procedure over and over.
I am including this as a help to someone who may be curious about how I solved this, but technically, MaximumBoy pointed me to the direct answer to my question, and for that reason I am going to vote for his answer as the correct one. I couldn't figure out how to do it Maximum's way, but that is because I know very little of SQL.
This is how I accomplished what I wanted. NOTICE THAT I changed the table name from "areasTable" to "areas" in my solution.
First way,
SELECT
"ROAD_NAME"
FROM
addresses
JOIN areas ON ST_Contains(areas.geom, addresses.geom)
WHERE
areas. "Name" ILIKE 'KACHINA';
The second way to accomplish this is the following,
SELECT
addresses."ROAD_NAME"
FROM
areas, addresses
WHERE
areas."Name" ILIKE 'KACHINA'
AND ST_Contains(areas.geom, addresses.geom);
The first one is a little bit slower than the second query, but this is from my empirical observations.

POSTGIS "ST_Contains" returns a empty query

I have imported two shape-files using QGIS into pgAdmin 4 (PostgreSQL), I use the PostGIS extension to be able to access spatial commands.
I want to check all the POIS (points) that are included in the Gemeinden (multipolygon) table. To accomplish that I use the spatial command "ST_Contains" ([postgis.net documentation regarding the command])1. Contrary to the fact that the points are actually in the polygons, the returned query is empty (see QGIS and output screenshot). What could be the issue? Any help would be appreciated. Thank you in advance!
Output - pgAdmin
The command I use:
SELECT * FROM public."POIS" AS pois INNER JOIN public."Gemeinden" AS gem
ON (1 = 1)
WHERE ST_Contains(gem.geom, pois.geom) = true;
My tables:
POIS table content
[3
Gemeinden table content
[4
QGIS Screenshots:
Both shape-files together:
[5
Only the POIS shape-file:
[6
Only the Gemeinden shape-file:
[7
Update:
I have created a polygon table out of the multi-polygons using the command
CREATE TABLE polygon_table AS
SELECT id, public."Gemeinden".kg_nr, public."Gemeinden".kg, (ST_DUMP(geom)).geom::geometry(Polygon,4326) AS geom FROM public."Gemeinden";
Afterwards I've updated the SRID of both the POIS table and the newly created one using :
SELECT UpdateGeometrySRID('polygon_table','geom',4326);
and
SELECT UpdateGeometrySRID('POIS','geom',4326);
Sadly,
SELECT pois.* FROM public."POIS" AS pois JOIN public."polygon_table" AS
gem
ON ST_intersects(gem.geom, pois.geom);
still returns a empty query.
Any ideas? Thank you in advance!
First of all make sure the SRID of the both table must be same. If it is not same then spatial queries wont work.
Secondly convert the multipolygons to single polygons. Following link may help
PostGIS - convert multipolygon to single polygon
Finally the following query would be enough if you just want to get the POIS that intersects the polygons
SELECT pois.* FROM public."POIS" AS pois JOIN public."Gemeinden" AS gem
ON ST_intersects(gem.geom, pois.geom);
I have resolved the problem by going back to QGIS and saving both previously imported shape-files as the same SRID. Apparently, my code that converted the SRID in the database did not work.
Right click on the shape-file
Selecting the SRID
Note: I have done this for both shape-files, just to be sure.
Another factor that may have influenced the outcome was the selection of the "convert to single polygon" box while importing into the database from QGIS.
The box that I ticked for both shape-files while importing
PS: I use the German version of QGIS

Merge two datasets duplicate BY variables Or I want to make following form

I am a novice in SAS program.
I have a question about merging two dataset.
The two data sets look like (please click this Image link (Excel sheet image):
Please let me know key concepts or code to make this happen!
I have searched the answer through Googling etc., but there is no site that exactly solve what I want.
(If it is possible to tackle above question without PROC SQL.)
To get the desired result you should do a cartesian product (Cross join) which returns all the rows in all tables. Each row in table1 is paired with all the rows in table2. I have used Proc SQL to do this and I am eager to see how this can be done using Data step. Here's what I know,
Proc Sql;
create table test_merge as
select a.*, b.type_rhs, b.rhs1, b.rhs2
from test a, test11 b
where a.yearmonth=b.yearmonth
;
quit;
Again, I am new to SAS as well and I think this is one of the ways to create the desired output.
When working with huge data, you will see a note in log that says "The execution of this query involves performing one or more Cartesian product joins that can not be optimized."

Postgis and Postgres: How to perform a ST_Contains query with geometry array?

I have a boundary which is stored in a geometry array. (like {...,...,...})
My goal is to perform a ST_Contains query. I want see whether a node is inside that boundary or not.
I tried something like
SELECT ST_Contains(ST_Polygonize((SELECT CAST(bt.geomarray AS geometry[]) FROM boundarytable AS bt)), nodetable.geom)
But I always get errors like "Invalid hex character (,) encountered".
Can anybody show me the right way to do this?
Now that I know how to do it, I'm answering this question by myself.
We do not have to use an array. We step through each node's geom and create the polygon. We store the polygon in polygontable. (Notice: don't forget you need the polygon to be closed, so you have to add the first node as last node again in boundarytable before you perform the query. Otherwise you will get an error):
SELECT ST_MakePolygon(ST_MakeLine(bt.geom)) AS geomboundary
INTO TABLE polygontable
FROM boundarytable AS bt
GROUP BY bt.dummy -- (just a constant value to round up all bt.geom)
Then we can perform the ST_Contains query like
SELECT *, ST_Contains((SELECT geomboundary FROM polygontable), anytable.geom)

How to do a SQL query using columns from a related table?

I've got three related SQL tables, simplified they look like this:
ShopTable
[ShopID]
ShelfTable
[ShelfID]
[ShopID]
InventoryTable
[ShelfID]
[Value]
[ShopID] and [ShelfID] are relations. Now what I want to do is get the SUM of [Value] for one [ShopID], but this obviously won't work since [ShopID] ain't part of InventoryTable:
SELECT SUM([Value]) WHERE [ShopID] = '1'
How do I have to write the query to filter the InventoryTable using the ShopID?
SELECT SUM(i.value)
FROM shelfTable s
JOIN inventoryTable i
ON i.shelfId = s.shelfId
WHERE s.shopId = 1
This is a fundamental question about relations between tables, so I'll provide some detail, hoping that you can use some of these ideas when writing SQL queries in the future.
Let's start with one basic thing first. [ShopID] could refer to two different but related columns, one in [ShopTable] and one in [ShelfTable]. The same things applies to [ShelfID]. It's useful to always specify the table.
You describe [ShopID] and [ShelfID] as "relations." As Damien_The_Unbeliever has commented, those columns are, in fact, two pairs of primary and foreign keys. That is, [ShelfTable].[ShelfID] identifies a "shelf" record, and [InventoryTable].[ShelfID] relates an "inventory item" (whatever that is) to a "shelf." (It's not always possible to interpret rows in a database this naively, but I'm willing to guess I'm not too far off from reality.)
Likewise, each "shelf" belongs to one "shop," and [ShelfTable].[ShopID] refers to that specific "shop." Notice that because we have the value of [ShopID] already (I'll call it "#MyShopID"), we don't even need the [ShopTable] here. We can just use [ShelfTable].[ShopID] to filter for the "shelves" we're interested in.
You're asking to get the sum total of [InventoryTable].[Value] for one [ShopID] value, but [ShopID] doesn't show up in [InventoryTable]. That's where your (inner) join comes into play. You know that you'll be adding up values from [InventoryTable], but you've got to specify the particular "shop." You specify #MyShopID for [ShelfTable].[ShelfID], which will do your filtering in [InventoryTable] for you.
One final thing before composing the query. I'm assuming that you haven't oversimplified your tables too much, and that [Value] is the total value of each "inventory item," and not just a unit value. If it wasn't, we'd have to multiply values by quantities, etc., but I'll let you check your own work here.
So, here's what we do:
We select FROM the [InventoryTable]
but we INNER JOIN to the [ShelfTable] on [ShelfID] from both tables
and we only want "shelves" from one "shop," i.e. WHERE [ShelfTable].[ShopID] = #MyShopID
and then we SELECT the SUM([InventoryTable].[Value])
and we're done. In SQL, let's remove the brackets, provide some table aliases, and we'll get a query that looks like this:
SELECT SUM(inv.Value)
FROM InventoryTable AS inv
INNER JOIN ShelfTable AS shf ON shf.ShelfID = inv.ShelfID
WHERE shf.ShopID = #MyShopID
;
Here are a few take-away points to consider. Notice we handled the FROM clause first. You'll always want to do that.
You'll also want a "driving table" to start with, in this case, [InventoryTable]. The other tables in your join add extra information and provide you a means to filter, but don't otherwise interfere with your summing up. More complex queries don't offer such an obvious luxury, but we're not getting too fancy here.
You'll also note, just briefly, that because [ShelfID] is a primary key in [ShelfTable], those [ShelfID]'s are unique values in [ShelfTable], and so each "inventory" thing belongs to a single "shelf." So the join won't cause us to double-count values. That's a good thing to remember when you're not dealing with primary and foreign keys, like we're doing here.
Hope that helps. And I hope I didn't come across as too pedantic.