I have tables like this:
CREATE TABLE postcode_area_boundaries
(
ogc_fid INTEGER,
wkb_geometry GEOMETRY(MultiPolygon,3857),
postarea VARCHAR(2),
area_km DOUBLE PRECISION,
area_mi DOUBLE PRECISION,
);
CREATE TABLE postcode_area_points
(
ogc_fid INTEGER PRIMARY KEY NOT NULL,
wkb_geometry GEOMETRY(Point,3857),
postcodearea VARCHAR(254),
postcodeareaname VARCHAR(254)
);
I have also files:
Postcode Area Boundaries.MID
"AB","Aberdeen"
POLYGON((383707 866131,383465 866240,383302 866387,383202 866505,383089 866586,.....))
"AL","St Albans"
POLYGON((526248 203348,....))
.......
Postcode Area Boundaries.MIF
VERSION 300
DELIMITER ","
COORDSYS EARTH PROJECTION 8,79,"m",-2,49,0.99960127,400000,-100000
COLUMNS 2
POSTCODEAREA CHAR (0)
POSTCODEAREANAME CHAR (0)
DATA
POINT 384222.000 819125.000
POINT 518661.000 209809.000
POINT 407763.000 285514.000
POINT 371106.000 147748.000
.... as many points as many was areas in MID file (about 126)
I probably should use ogr2ogr but have no idea how. I am trying with commands like this:
ogr2ogr -f PostgreSQL PG:"<dbconn>" "Postcode Area Boundaries.MIF" -t_srs EPSG:3857 -nlt MULTIPOLYGON -overwrite -nln postcode_area_boundaries
But I have errors like this:
Warning 1: Geometry to be inserted is of type Point, whereas the layer
geometry type is Multi Polygon. Insertion is likely to fail ERROR 1:
INSERT command for new feature failed. ERROR: Geometry type (Point)
does not match column type (MultiPolygon)
Can anyone help me with this?
Related
Question(*):
The total number of cases and deaths as a percentage of the population, for each country (with country, % cases of population, % deaths of population as columns)
I have two tables :
countriesAffected(countriesAndTerritories,geoId,countryterritoryCode,popData2019,continentExp)
victimsCases(dateRep,cases,deaths,geoId)
where primary key(geoid)
I tried to do (*) by this method:
SELECT countriesAndTerritories, (100 *SUM(victimsCases.cases) / popData2019)as "cases" ,(100 * SUM(deaths) / popData2019) as "deaths"
FROM countriesAffected
INNER JOIN victimsCases ON victimsCases.geoId = countriesAffected.geoId
GROUP BY countriesAndTerritories
ORDER BY countriesAndTerritories DESC;
Error: near line 2: near "SELECT countriesAndTerritories": syntax error
But for some reason I get all types of syntax errors, i tried to sort it out but with no results. And not sure where did i went wrong.
If you are getting the error Error: near line 2: near "SELECT countriesAndTerritories": syntax error then the issue is with LINE 1 (perhaps no ; at the end of line 1).
Otherwise your query works albiet probably not as intended (as you may well want decimal places for the percentages).
Consider the following (that shows your SQL with additional SQL added to work as intended (see casesV2 and deathsV2 that utilise CAST to force INTEGER to REAL)).
DROP TABLE If EXISTS victimsCases;
DROP TABLE IF EXISTS countriesAffected;
CREATE TABLE IF NOT EXISTS countriesAffected (countriesAndTerritories TEXT,geoId INTEGER PRIMARY KEY,countryterritoryCode TEXT,popData2019 INTEGER,continentExp TEXT);
CREATE TABLE IF NOT EXISTS victimsCases (dateRep TEXT,cases INTEGER ,deaths INTEGER,geoId INTEGER);
INSERT INTO countriesAffected VALUES
('X',1,'XXX',10000,'?'),('Y',2,'YYY',20000,'?'),('Z',3,'ZZZ',30000,'?')
;
INSERT INTO victimsCases VALUES
('2019-01-01',100,20,1),('2019-01-02',100,25,1),('2019-01-03',100,15,1),
('2019-01-01',30,5,2),('2019-01-02',33,2,2),
('2019-01-01',45,17,3),('2019-01-02',61,4,3),('2019-01-03',75,7,3)
;
SELECT countriesAndTerritories,
(100 *SUM(victimsCases.cases) / popData2019)as "cases", /* ORIGINAL */
(100 * SUM(deaths) / popData2019) as "deaths", /* ORIGINAL */
CAST(SUM(victimsCases.cases) AS FLOAT) / popData2019 * 100 AS "casesV2",
CAST(SUM(victimscases.deaths) AS FLOAT) / popData2019 * 100 as "deathsV2"
FROM countriesAffected
INNER JOIN victimsCases ON victimsCases.geoId = countriesAffected.geoId
GROUP BY countriesAndTerritories
ORDER BY countriesAndTerritories DESC;
DROP TABLE If EXISTS victimsCases;
DROP TABLE IF EXISTS countriesAffected;
The result of the above is :-
I have a linestring:
LINESTRING( -43.0965167 -22.8808585,-43.0980368 -22.8807975,-43.0986518
-22.8807735,-43.0990955 -22.8807701,-43.0991492 -22.8807697,-43.1005956
-22.8807353,-43.1013221 -22.8807107,-43.1016904 -22.8807003,-43.1019484
-22.8806902,-43.1020398 -22.8806866,-43.102591 -22.8806801,-43.1029336
-22.8806666,-43.1036051 -22.8806402,-43.1039349 -22.8806272,-43.1042967
-22.880613,-43.1061912 -22.8805398 )
Now I can select all points at a distance "x" from this line ( around the line ). I already tried Find the nearest points along the linestring in specified distance limit and order with no success ( always take a lot of points in a box like distribution ). This is a piece of code I started to write:
select p.way,p.name from planet_osm_point p where ST_DWithin(
ST_Transform( theLineGeom, 4326), ST_Transform( p.way,4326 ), 0.9)
limit 50;
I think you are getting lots of points because ST_DWithin uses the unit of the geometries srid to perform the calculation.
boolean ST_DWithin(geometry g1, geometry g2, double precision distance_of_srid);
So you are getting all the points with 0.9 degrees from your linestring.
You could use
boolean ST_DWithin(geography gg1, geography gg2, double precision distance_meters);
converting your geometries to geography.
Otherwise you could use another srid.
Solved. I just get too many points because the limit was too big. If I have 2 points near the route and tell the query to give me the first 50 then 48 points will be far from the line but inside the bounding box. This is why the box like distribution I saw.
select * from pointscanner('<geomRoute_WILL_BE_HERE>') where round(distance::numeric, 5) < 500 /* meters */
CREATE OR REPLACE FUNCTION public.pointscanner( IN routeGeometry text)
RETURNS TABLE(way geometry, name text, distance double precision, tags hstore, operator text, admin_level text, z_order integer) AS
$BODY$
DECLARE
geomRoute geometry;
routeBB box2d;
BEGIN
geomRoute = ST_GeomFromText('MULTILINESTRING(
(-43.1761935 -22.90642,-43.1755606 -22.9064116,-43.1754828 -22.9064106,-43.1753675 -22.9064091),
(-43.176696 -22.9064062,-43.1761935 -22.90642),(-43.176805 -22.9064027,-43.176696 -22.9064062),
(-43.1776911 -22.9049927,-43.1776625 -22.9050849,-43.1775227 -22.9055527,-43.1775045 -22.9056041,-43.1774504 -22.9057582),
(-43.1782012 -22.9036858,-43.1778613 -22.9045254,-43.1777841 -22.9047287,-43.1777446 -22.9048326,-43.1777179 -22.9049164,-43.1776911 -22.9049927),
(-43.1772218 -22.9063929,-43.1771252 -22.9063944,-43.1771118 -22.9063946,-43.1769202 -22.9064008,-43.176805 -22.9064027),
(-43.1774504 -22.9057582,-43.1773182 -22.9061373,-43.1772868 -22.9062205,-43.1772218 -22.9063929),
(-43.1834587 -22.9028997,-43.1833984 -22.9028862,-43.1830022 -22.9027778,-43.1825446 -22.9026278,-43.1821151 -22.9024891,-43.1816491 -22.9023374,-43.1815912 -22.9023186,-43.1813461 -22.9022388),
(-43.1793173 -22.901581,-43.1791549 -22.9015418,-43.179105 -22.9015365,-43.1790457 -22.9015482,-43.1790174 -22.9015689,-43.178994 -22.9016082),
(-43.1788184 -22.9020931,-43.1786726 -22.9025241,-43.1786518 -22.9025769,-43.1786063 -22.9026931),
(-43.1813461 -22.9022388,-43.1806028 -22.9019969,-43.1805417 -22.901977,-43.1799074 -22.9017705),
(-43.1799074 -22.9017705,-43.1797658 -22.9017244,-43.1793732 -22.9015989,-43.1793173 -22.901581),
(-43.178994 -22.9016082,-43.1788184 -22.9020931),(-43.1784337 -22.9031366,-43.1782012 -22.9036858),
(-43.1786063 -22.9026931,-43.17848 -22.9030174,-43.178461 -22.9030662,-43.1784337 -22.9031366))',4326);
routeBB := ST_Extent(geomRoute);
RETURN QUERY
SELECT pt.way, pt.name, ST_Distance( geomRoute, ST_Transform(pt.way,4326) ) * 111195 as distance,
pt.tags, pt.operator, pt.admin_level, pt.z_order
FROM planet_osm_point pt
where routeBB && ST_Transform(pt.way,4326);
END; $BODY$
LANGUAGE plpgsql VOLATILE
I have a custom type "nameage" and a table "namesages".
CREATE TYPE nameage AS(
name_ varchar(50),
age smallint
);
CREATE TABLE namesages(
id serial,
namesandages nameage[]
);
INSERT INTO namesages(namesandages) VALUES(ARRAY[['john', 24],['david', 38]]::nameage[]);
Why does this query give error?;
ERROR: malformed record literal: "john"
LINE 1: insert into namesages(namesandages) values(ARRAY[['john', 24...
^
DETAIL: Missing left parenthesis.
********** Error **********
What you meant to do was this:
INSERT INTO namesages(namesandages)
VALUES(ARRAY[ROW('john', 24),ROW('david', 38)]::nameage[]);
This creates a one dimensional array of user-defined composite types. I'm not sure what you intended to do when you defined a two-dimensional array...
I am using sqlite3 python modules and th following code returns the error
InterfaceError: Error binding parameter 0 - probably unsupported type
Note I have already tried with normal (non unicode) strings and the result is the same
# get database cursor
cur = dbConnection.cursor()
# create table for prices
cur.execute( """
create table if not exists
prices( time text,
mid integer,
exid text,
selid integer,
priceone real,
sometext text,
price2 real,
primary key (time, mid, exid, selid, priceone)
foreign key (time, mid, exid, selid) references selection(time, mid, exid,selid) )""" )
#insert price
tuple = (u'20120228153239788135', 104982590, 1, 4764315, 1.99, u'B', 0.07)
cur.execute( "insert into prices values (?,?,?,?,?,?,?)", tuple)
This code works fine for me.
However, have you changed your table schema at all? Because you add the
create if not exists
it is likely you changed something but the DB (file) wasn't updated since you have this.
Also, you are passing in an int for exid even though the type is text. It will automatically convert it but still shouldn't do it.
I have some filters in the following form:
Object A
+/- Start End
----------------------------------------------
+ 000000080000 000000090000
- 000000800500
+ 054*
Object B
+/- Start End
----------------------------------------------
+ 000000090000 000000100000
+ 00??00900500
- 000000900500
+ 055*
It means:
Numbers between 000000080000 and 000000090000 except 000000800500, and numbers starting with 054 are associated with object A.
Numbers between 000000090000 and 000000100000 except 000000900500, numbers matching 00??00900500 (except 000000900500 of course), and numbers starting with 055 are associated with object B.
Example of the table structure:
CREATE TABLE dbo.Filter
(
IDFilter int IDENTITY PRIMARY KEY
)
CREATE TABLE dbo.FilterRow
(
IDFilterRow int IDENTITY PRIMARY KEY
,IDFilter int FOREIGN KEY REFERENCES dbo.Filter(IDFilter) NOT NULL
,Operator bit --0 = -, 1 = + NOT NULL
,StartNumber varchar(50) NOT NULL
,EndNumber varchar(50)
)
CREATE TABLE dbo.[Object]
(
IDObject int IDENTITY PRIMARY KEY
,Name varchar(10) NOT NULL
,IDFilter int FOREIGN KEY REFERENCES dbo.Filter(IDFilter) NOT NULL
)
I need a way to make sure no numbers can get associated with more than 1 object, in SQL (or CLR), and I really have no clue how to do such a thing (besides bruteforce).
I do have a CLR function Utils.fIsInFilter('?8*', '181235467895') that supports wildcards and would return 1, if it helps...
Can you use a CLR function in SQL 2005?
It's possible in raw SQL using LIKE JOINS (where ? becomes [0-9] and * becomes %), perhaps followed by CAST, but this is what CLR functions are for...