Pgrouting insert od columns into pgr_dijkstra query - postgis

I try to calculate travels between a pair list of 2 layers : origin and destination.
I create a table of combinaison between this two layers with vertices id in vertices_o for origin and vertices_d for destination.
I call the columns into this query.
The combination table
The query
CREATE TABLE travel.results AS
(SELECT seq, path_seq, node, edge, di.cost, agg_cost, the_geom FROM pgr_dijkstra('
SELECT gid as id,
source::integer,
target::integer,
length_m::double precision as cost
FROM travel.ways',
vertices_o, vertices_d, true) as di
JOIN travel.ways ways_vertices_pgr
ON di.edge = ways_vertices_pgr.gid);
He didn't recognize the columns vertices_o and vertices_d.

Related

Update Row Order Category wise in SQL

I have two table Images and Category in SQL Database. The Images images contains imageorder column which right now contains random order, so I wanted to do is re-arrange that order starting from 1 and so on but it should be category wise.
For example, Category table contains Twowheeler and Fourwheeler categories and Images table contains 10 rows out of 4 rows for Twowheeler and 6 rows for Fourwheeler.
SO, imageorder column should update like 1,2,3,4 for Twowheeler and 1,2,3,4,5,6 for Fourwheeler.
It should be something like this:
WITH DataSource AS
(
SELECT *
,ROW_NUMBER() OVER(PARTITION BY categoryid ORDER BY imageOrder) rowID
FROM Images
)
UPDATE IMages
SET ImageOrder = DS.rowID
FROM Images I
INNER JOIN DataSoruce DS
ON I.ImageId = DS.ImageID;
The idea is to use ROW_NUMBER to order the images. We are using PARTITION BY because we want to reset the order for each category. Also, we need to use a Common Table Expression to store this data and then to use it in the INNER JOIN statement - we are not allowed to use ROW_NUNMBER function directly in UPDATE statement.

How to query postgis data by closest point and only return results for that point?

I have a postgis table of points, 460 million records. It has a timestamp & point column.
I'm building graphs based on this data, a list of values for each timestamp that belong to the closest point, leaflet sends the lat/long from the map (where the user clicked) to the script that generates the chart-ready data.
SELECT thevalue
FROM thetable
WHERE ST_DWithin (thepoint, ST_MakePoint($get_lon, $get_lat), 0.04)
ORDER BY thedate
LIMIT 1000
This works great (for some clicks) but there has to be a better/faster way, I'd like the query to know what point to listen to and only return values for that point. Is there a better function for this requirement?
What king of geometry do you have? what projection are you using?
I'm going to assume that your points are in wgs84 (epsg:4326)
If you want distances to be accurate, it's better to use geography in calculations:
alter points_table add column geog geography
update points_table set geog = geom::geography
create an index, and run cluster and analyze to speed up queries
create index my_index_geog on points_table using gist(geog) /* change geog for geom if using geometry */
cluster points_table using my_index_geog
analyze points_table
to get the closest point:
SELECT point_id
FROM points_table
ORDER BY geog <-> ST_SetSrid(ST_MakePoint($get_lon, $get_lat),4326)::geography limit 1;
all together to get the values:
select value
from table
where point_id = (SELECT point_id
FROM points_table
ORDER BY geog <-> ST_SetSrid(ST_MakePoint($get_lon, $get_lat),4326)::geography limit 1)
order by thedate
limit 1000;
additionally I would suggest keeping a table that contains only the points id's and the geometry/geography so the closest-point query runs faster. If you create such table, called only_points, the query becomes:
select value
from table
where point_id = (SELECT point_id
FROM only_points
ORDER BY geog <-> ST_SetSrid(ST_MakePoint($get_lon, $get_lat),4326)::geography limit 1)
order by thedate
limit 1000;
If you need to keep using geometry, then you'll need to create the index on the geometry, cluster based on geom and run the query:
select value
from table
where point_id = (SELECT point_id
FROM points_table
ORDER BY geom::geography <-> ST_SetSrid(ST_MakePoint($get_lon, $get_lat),4326)::geography limit 1)
order by thedate
limit 1000;
It will be slower, however, because you'll be converting to geography on each step
see KNN in Postgis and PostGIS geography type and indexes

SQL Server FullText Search with Weighted Columns from Previous One Column

In the database on which I am attempting to create a FullText Search I need to construct a table with its column names coming from one column in a previous table. In my current implementation attempt the FullText indexing is completed on the first table Data and the search for the phrase is done there, then the second table with the search results is made.
The schema for the database is
**Players**
Id
PlayerName
Blacklisted
...
**Details**
Id
Name -> FirstName, LastName, Team, Substitute, ...
...
**Data**
Id
DetailId
PlayerId
Content
DetailId in the table Data relates to Id in Details, and PlayerId relates to Id in Players. If there are 1k rows in Players and 20 rows in Details, then there are 20k rows in Data.
WITH RankedPlayers AS
(
SELECT PlayerID, SUM(KT.[RANK]) AS Rnk
FROM Data c
INNER JOIN FREETEXTTABLE(dbo.Data, Content, '"Some phrase like team name and player name"')
AS KT ON c. DataID = KT.[KEY]
GROUP BY c.PlayerID
)
…
Then a table is made by selecting the rows in one column. Similar to a pivot.
…
SELECT rc.Rnk,
c.PlayerID,
PlayerName,
TeamID,
…
(SELECT Content FROM dbo.Data data WHERE DetailID = 1 AND data.PlayerID = c.PlayerID) AS [TeamName],
…
FROM dbo.Players c
JOIN RankedPlayers rc ON c. PlayerID = rc. PlayerID
ORDER BY rc.Rnk DESC
I can return a ranked table with this implementation, the aim however is to be able to produce results from weighted columns, so say the column Playername contributes to the rank more than say TeamName.
I have tried making a schema bound view with a pivot, but then I cannot index it because of the pivot. I have tried making a view of that view, but it seems the metadata is inherited, plus that feels like a clunky method.
I then tried to do it as a straight query using sub queries in the select statement, but cannot due to indexing not liking sub queries.
I then tried to join multiple times, again the index on the view doesn't like self-referencing joins.
How to do this?
I have come across this article http://developmentnow.com/2006/08/07/weighted-columns-in-sql-server-2005-full-text-search/ , and other articles here on weighted columns, however nothing as far as I can find addresses weighting columns when the columns were initially row data.
A simple solution that works really well. Put weight on the rows containing the required IDs in another table, left join that table to the table to which the full text search had been applied, and multiply the rank by the weight. Continue as previously implemented.
In code that comes out as
DECLARE #Weight TABLE
(
DetailID INT,
[Weight] FLOAT
);
INSERT INTO #Weight VALUES
(1, 0.80),
(2, 0.80),
(3, 0.50);
WITH RankedPlayers AS
(
SELECT PlayerID, SUM(KT.[RANK] * ISNULL(cw.[Weight], 0.10)) AS Rnk
FROM Data c
INNER JOIN FREETEXTTABLE(dbo.Data, Content, 'Karl Kognition C404') AS KT ON c.DataID = KT.[KEY]
LEFT JOIN #Weight cw ON c.DetailID = cw.DetailID
GROUP BY c.PlayerID
)
SELECT rc.Rnk,
...
I'm using a temporary table here for evidence of concept. I am considering adding a column Weights to the table Details to avoid an unnecessary table and left join.

Selecting multiple rows of many to many related columns into one column in SQL SERVER?

I have the following DB Tables with SQL Server
Booking(bookingID,customerName,branchID,RefNumber,...)
Trip(TripID,vehicleID,...)
BookingToTripMap(TripID,bookingID)
Branch(branchID, branchName)
Vehicle(vehicleID,vehicleNumber)
There is a one to one relationship between (Booking,Branch) and (Trip, Vehicle) and Many to many relationship between Booking, Trip which is saved in the table BookingToTripMap.
Now I want to extract a query that would return the following
Booking.RefNumber Booking.CustomerName Vehicle.VehicleNumber
(All vehicle numbers in one cell)
Here is your query
SELECT B.RefNumber, B.CustomerName, V.VehicleNumber
FROM ((Booking AS B INNER JOIN BookingToTripMap AS BT
ON B.bookingID = BT.bookingID) INNER JOIN TRIP as T
ON T.TripID = BT.TripID) INNER JOIN Vehicle as V
ON V.vehicleID = T.vehicleID
I would add the field bookingID to the table Trip, it seems that the table BookingToTripMap doesn't add any value to your database.
Also, if your vehicle's numbers are unique, you could change the primary key in the Vehicle table to vehicleNumber, and change the same columns in the Trip table. Thus you could retrieve the vehicleNumber directly from the Trip table.
I'm just guessing in that, based on the given information.
Regards,

How to fetch an object graph at once?

I'm reading a book, where the author talks about fetching an row + all linked parent rows in one step. Like fetching an order + all it's items all at once. Okay, sounds nice, but really: I've never seen an possibility in SQL to ask for - lets say - one order + 100 items? How would this record set look like? Would I get 101 rows with merged fields of both the order and the item table, where 100 rows have a lot of NULL values for the order fields, while one row has a lot of NULL values for the item fields? Is that the way to go? Or is there something much cooler? I mean... I never heard of fetching arrays onto a field?
A simple JOIN would do the trick:
SELECT o.*
, i.*
FROM orders o
INNER JOIN order_items i
ON o.id = i.order_id
The will return one row for each row in order_items. The returned rows consist of all fields from the orders table, and concatenated to that, all fields from the order_items table (quite literally, the records from the tables are joined, that is, they are combined by record concatenation)
So if orders has (id, order_date, customer_id) and order_items has (order_id, product_id, price) the result of the statement above will consist of records with (id, order_date, customer_id, order_id, product_id, price)
One thing you need to be aware of is that this approach breaks down whenever there are two distinct 'detail' tables for one 'master'. Let me explain.
In the orders/order_items example, orders is the master and order_items is the detail: each row in order_items belongs to, or is dependent on exactly one row in orders. The reverse is not true: one row in the orders table can have zero or more related rows in the order_items table. The join condition
ON o.id = i.order_id
ensures that only related rows are combined and returned (leaving out the condition would retturn all possible combinations of rows from the two tables, assuming the database would allow you to omit the join condition)
Now, suppose you have one master with two details, for example, customers as master and customer_orders as detail1 and customer_phone_numbers. Suppose you want to retrieve a particular customer along with all is orders and all its phone numbers. You might be tempted to write:
SELECT c.*, o.*, p.*
FROM customers c
INNER JOIN customer_orders o
ON c.id = o.customer_id
INNER JOIN customer_phone_numbers p
ON c.id = p.customer_id
This is valid SQL, and it will execute (asuming the tables and column names are in place)
But the problem is, is that it will give you a rubbish result. Assuming you have on customer with two orders (1,2) and two phone numbers (A, B) you get these records:
customer-data | order 1 | phone A
customer-data | order 2 | phone A
customer-data | order 1 | phone B
customer-data | order 2 | phone B
This is rubbish, as it suggests there is some relationship between order 1 and phone numbers A and B and order 2 and phone numbers A and B.
What's worse is that these results can completely explode in numbers of records, much to the detriment of database performance.
So, JOIN is excellent to "flatten" a hierarchy of items of known depth (customer -> orders -> order_items) into one big table which only duplicates the master items for each detail item. But it is awful to extract a true graph of related items. This is a direct consequence of the way SQL is designed - it can only output normalized tables without repeating groups. This is way object relational mappers exist, to allow object definitions that can have multiple dependent collections of subordinate objects to be stored and retrieved from a relational database without losing your sanity as a programmer.
This is normally done through a JOIN clause. This will not result in many NULL values, but many repeated values for the parent row.
Another option, if your database and programming language support it, it to return both result sets in one connection - one select for the parent row another for the related rows.

Resources