Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion delhi_districts.sql
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ ContainedBy(TripId, Name, AtTime) AS (
FROM Trips t, Districts d
WHERE eIntersects(t.Trip, d.Geom)
ORDER BY t.TripId, d.Name )
SELECT m1.TripId, m1.Name, m1.AtTimestamp, c.AtTime, m2.AtTimestamp
SELECT m1.TripId, m1.Name, m1.AtTimestamp AS StartTimestamp, c.AtTime, m2.AtTimestamp AS EndTimestamp
FROM Meets m1, ContainedBy c, Meets m2
WHERE m1.TripId = c.TripId AND m1.Name = c.Name AND
m2.TripId = c.TripId AND m2.Name = c.Name AND
Expand Down
131 changes: 60 additions & 71 deletions delhi_grid.sql
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ Episode(TripId, EpisodeId, AtTime, CellId, Pm25, Trend) AS (
AtTime), AtTime, CellId, Pm25, Trend
FROM EpisodeStart ),
EpisodeDuration(TripId, EpisodeId, AtTime, Trend, Cells, Pm25) AS (
SELECT TripId, EpisodeId, spanUnion(AtTime ORDER BY AtTime),
SELECT TripId, EpisodeId, spansetUnion(AtTime ORDER BY AtTime),
merge(array_agg(Trend ORDER BY Trend)),
tintSeq(array_agg(tint(CellId, lower(AtTime)) ORDER BY AtTime)),
merge(array_agg(Pm25 ORDER BY Pm25))
FROM Episode
GROUP BY TripId, EpisodeId
HAVING duration(spanUnion(AtTime ORDER BY AtTime)) >= interval '1.5 minutes'
HAVING duration(spansetUnion(AtTime ORDER BY AtTime)) >= interval '1.5 minutes'
AND COUNT(*) >= 2 ),
EpisodePair(TripId, IncrEpisode, DecrEpisode) AS (
SELECT e1.TripId, e1.EpisodeId, e2.EpisodeId
Expand Down Expand Up @@ -228,7 +228,7 @@ ORDER BY TripId, AtTime;
-------------------------------------------------------------------------------
/*
Query 5.11. Trips that travel all their way under a temperature higher than
25 degrees and such that at in at least two episodes longer than thirty minutes,
25 degrees such that in at least two episodes longer than ten minutes,
the Pm25 is higher than 150.
*/

Expand All @@ -242,7 +242,8 @@ WITH TripTemp(TripId) AS (
LowerPm25(TripId, StartTime, EndTime, CellId, Pm25, StartEpisode) AS (
SELECT TripId, StartTime, EndTime, CellId, Pm25,
CASE
WHEN whenTrue(Pm25 #> 150)
WHEN Pm25 <= 150 OR LAG(Pm25) OVER
(PARTITION BY TripId ORDER BY StartTime) <= 150
THEN 1 ELSE 0
END
FROM TripCells
Expand Down Expand Up @@ -274,44 +275,37 @@ ORDER BY TripId, StartTime;
-- Time: 107.508 ms

-- TEMPORAL VERSION

-- In the continuous model the episode is the exact temporal extent where Pm25 > 150,
-- computed with whenTrue(Pm25 #> 150) on the trip's tfloat (no per-cell reduction).
-- The temperature condition "all their way" is the always-predicate Temperature %> 25.
-- As the paper notes, the continuous approach yields more/more-precise episodes than the
-- discrete one (here 4 trips vs 2), since episodes are not split at cell boundaries.
DROP TABLE IF EXISTS TGQ5_12;
CREATE TABLE TGQ5_12(TripId, EpisodeId, AtTime, Duration, Cells, Pm25) AS
WITH TripTemp(TripId) AS (
SELECT TripId
FROM TripTiles
WITH TripTemp(TripId, Pm25) AS (
SELECT TripId, Pm25 FROM Trips
WHERE tfloat(Weather, 'Temperature', 'step') %> 25 ),
LowerPm25(TripId, AtTime, CellId, Pm25, StartEpisode) AS (
SELECT TripId, AtTime, CellId, Pm25,
CASE
WHEN Pm25 <= 150 OR LAG(Pm25) OVER
(PARTITION BY TripId ORDER BY StartTime) <= 150
THEN 1 ELSE 0
END
FROM TripTiles
WHERE TripId IN (SELECT TripId FROM TripTemp) ),
Episode(TripId, EpisodeId, StartTime, EndTime, CellId, Pm25) AS (
SELECT TripId, SUM(StartEpisode) OVER
(PARTITION BY TripId ORDER BY StartTime), StartTime, EndTime, CellId, Pm25
FROM LowerPm25 ),
Pattern(TripId, EpisodeId, StartTime, EndTime, Duration, Cells, Pm25seq) AS (
SELECT TripId, EpisodeId, MIN(StartTime), MAX(EndTime),
MAX(EndTime) - MIN(StartTime), array_agg(CellId ORDER BY StartTime),
array_agg(ROUND(Pm25::numeric, 2) ORDER BY StartTime)
FROM Episode
WHERE Pm25 > 150
GROUP BY TripId, EpisodeId
HAVING MAX(EndTime) - MIN(StartTime) >= interval '10 minutes' AND
COUNT(*) >= 2 ),
Episode(TripId, Period, Pm25) AS (
SELECT TripId, unnest(spans(whenTrue(Pm25 #> 150))), Pm25
FROM TripTemp
WHERE whenTrue(Pm25 #> 150) IS NOT NULL ),
LongEpisode(TripId, Period, Pm25) AS (
SELECT TripId, Period, Pm25 FROM Episode
WHERE duration(Period) >= interval '10 minutes' ),
SelectedTrip(TripId) AS (
SELECT TripId
FROM Pattern
GROUP BY TripId
HAVING COUNT(*) >= 2 )
SELECT TripId, EpisodeId, StartTime, EndTime, Duration, Cells, Pm25seq
FROM Pattern
WHERE TripId IN (SELECT TripId FROM SelectedTrip)
ORDER BY TripId, StartTime;
SELECT TripId FROM LongEpisode GROUP BY TripId HAVING COUNT(*) >= 2 )
SELECT l.TripId,
row_number() OVER (PARTITION BY l.TripId ORDER BY l.Period) AS EpisodeId,
l.Period AS AtTime,
duration(l.Period) AS Duration,
(SELECT tintSeq(array_agg(tint(t.CellId, lower(t.AtTime)) ORDER BY lower(t.AtTime)))
FROM TripTiles t WHERE t.TripId = l.TripId AND t.AtTime && l.Period) AS Cells,
atTime(l.Pm25, l.Period) AS Pm25
FROM LongEpisode l
WHERE l.TripId IN (SELECT TripId FROM SelectedTrip)
ORDER BY l.TripId, AtTime;

-- SELECT 8

-------------------------------------------------------------------------------
/*
Expand Down Expand Up @@ -360,37 +354,35 @@ ORDER BY TripId, StartTime;
-- Time: 408.906 ms

-- TEMPORAL VERSION

-- The episode is the exact temporal extent where all three conditions hold simultaneously:
-- Pm25 > 300, cloudy (CloudCover > 0), and Humidity > 80, obtained with a temporal conjunction
-- whenTrue((Pm25 #> 300) & (CloudCover #> 0) & (Humidity #> 80)) over the trip's tfloats.
-- This mirrors the discrete Valid = (all three conditions) per-cell logic, but at instant
-- granularity (here 71 episodes vs 92; the continuous is stricter, requiring the conjunction
-- at every instant rather than over cell-aggregated values).
DROP TABLE IF EXISTS TQ5_13;
CREATE TABLE Q5_13 AS
WITH Segment(TripId, StartTime, EndTime, Pm25, CloudCover, Humidity, Valid) AS (
SELECT TripId, StartTime, EndTime, Pm25, (Weather->>'CloudCover')::numeric,
(Weather->>'Humidity')::numeric,
CASE
WHEN Pm25 > 300 AND (Weather->>'CloudCover')::numeric > 0 AND
(Weather->>'Humidity')::numeric > 80
THEN 1 ELSE 0
END
FROM TripTiles ),
SegmentPrev(TripId, StartTime, EndTime, Pm25, CloudCover, Humidity, Valid,
PrevValid) AS (
SELECT *, LAG(Valid) OVER (PARTITION BY TripId ORDER BY StartTime)
FROM Segment ),
Episode(TripId, EpisodeId, StartTime, EndTime, Pm25, CloudCover, Humidity, Valid,
PrevValid) AS (
SELECT TripId, SUM(CASE WHEN Valid = PrevValid THEN 0 ELSE 1 END) OVER
(PARTITION BY TripId ORDER BY StartTime), StartTime, EndTime, Pm25,
CloudCover, Humidity, Valid, PrevValid
FROM SegmentPrev )
SELECT TripId, EpisodeId, MIN(StartTime) AS StartTime,
MAX(EndTime) AS EndTime, MAX(StartTime) - MIN(StartTime) AS Duration,
array_agg(Pm25 ORDER BY StartTime) AS Pm25Seq,
array_agg(CloudCover ORDER BY StartTime) AS CloudCoverSeq,
array_agg(Humidity ORDER BY StartTime) AS HumiditySeq
CREATE TABLE TQ5_13(TripId, EpisodeId, AtTime, Duration, Pm25, CloudCover, Humidity) AS
WITH Cond(TripId, Periods, Pm25, Cloud, Humid) AS (
SELECT TripId,
whenTrue((Pm25 #> 300) & (tfloat(Weather, 'CloudCover', 'step') #> 0) &
(tfloat(Weather, 'Humidity', 'step') #> 80)),
Pm25, tfloat(Weather, 'CloudCover', 'step'), tfloat(Weather, 'Humidity', 'step')
FROM Trips ),
Episode(TripId, Period, Pm25, Cloud, Humid) AS (
SELECT TripId, unnest(spans(Periods)), Pm25, Cloud, Humid
FROM Cond WHERE Periods IS NOT NULL )
SELECT TripId,
row_number() OVER (PARTITION BY TripId ORDER BY Period) AS EpisodeId,
Period AS AtTime,
duration(Period) AS Duration,
atTime(Pm25, Period) AS Pm25,
atTime(Cloud, Period) AS CloudCover,
atTime(Humid, Period) AS Humidity
FROM Episode
GROUP BY TripId, EpisodeId
HAVING MAX(EndTime) - MIN(StartTime) >= '30 minutes' AND BOOL_AND(Valid = 1)
ORDER BY TripId, StartTime;
WHERE duration(Period) >= interval '30 minutes'
ORDER BY TripId, AtTime;

-- SELECT 71

-------------------------------------------------------------------------------
/*
Expand All @@ -399,7 +391,7 @@ one different cell in between.
*/

-- Overlapping patterns
DROP TABLE IF EXISTS Q5_14_Over;
DROP TABLE IF EXISTS Q5_14;
CREATE TABLE Q5_14 AS
SELECT s.TripId, g.Pos, s.CellSeq[g.Pos : g.Pos + 2] AS MatchSeq
FROM TripCellsSeq s
Expand Down Expand Up @@ -513,9 +505,6 @@ ORDER BY TripId;
-- SELECT 63
-- Time: 99.441 ms

DROP TABLE IF EXISTS TQ5_15;
CREATE TABLE TQ5_15 AS

DROP TABLE IF EXISTS TQ5_15;
CREATE TABLE TQ5_15 AS
-- Get the three previous visited cells
Expand Down
14 changes: 7 additions & 7 deletions delhi_points_trips.sql
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ WITH RestTrips(TripId, Pm25) AS (
whenTrue(tfloat(Weather, 'Temperature', 'step') #> 20) IS NOT NULL ),
IncrPm25(TripId, Pm25) AS (
SELECT TripId, unnest(sequences(atTime(Pm25,
whenTrue(segmentMinDuration(atValues(trend(Pm25) #> 0, true),
whenTrue(segmentMinDuration(atValue(trend(Pm25) #> 0, true),
interval '1.5 minute', false)))))
FROM RestTrips ),
DecrPm25(TripId, Pm25) AS (
SELECT TripId, unnest(sequences(atTime(Pm25,
whenTrue(segmentMinDuration(atValues(trend(Pm25) #< 0, true),
whenTrue(segmentMinDuration(atValue(trend(Pm25) #< 0, true),
interval '1.5 minute', false)))))
FROM RestTrips )
SELECT i.TripId, i.Pm25 AS IncrPm25, d.Pm25 AS DecrPm25
Expand All @@ -158,11 +158,11 @@ ORDER BY TripId, IncrPm25;
-------------------------------------------------------------------------------

SELECT DISTINCT TripId FROM q5_9 EXCEPT SELECT DISTINCT TripId FROM tq5_9 ORDER BY 1;
(0 rows)
-- (0 rows)

SELECT DISTINCT TripId FROM tq5_9 EXCEPT SELECT DISTINCT TripId FROM q5_9 ORDER BY 1;
2245
(1 row)
-- 2245
-- (1 row)

/*
The missing trip in q5_9 is 2245 and it is not considered in the non-temporal
Expand Down Expand Up @@ -243,10 +243,10 @@ ORDER BY TripId;
-------------------------------------------------------------------------------

SELECT DISTINCT tripid FROM tq5_10 EXCEPT SELECT DISTINCT tripid FROM q5_10 ORDER BY 1 LIMIT 5;
(0 rows)
-- (0 rows)

SELECT DISTINCT tripid FROM q5_10 EXCEPT SELECT DISTINCT tripid FROM tq5_10 ORDER BY 1 LIMIT 5;
(0 rows)
-- (0 rows)

-------------------------------------------------------------------------------

Expand Down
44 changes: 28 additions & 16 deletions paris_queries.sql
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ ORDER BY h.TourId;
*/

/*****************************************************************************/
/* COMENTED OUT
/* COMENTED OUT */
/*****************************************************************************/

/*
Expand Down Expand Up @@ -439,25 +439,37 @@ ORDER BY f.TourId;
*/

-- TEMPORAL VERSION

WITH Step(TourId, Tour) AS (
-- Each PoI visit is a segment of the temporal tour (a tjsonb). We extract the PoI
-- attributes with startValue(Seg)->>'...' and its start time with startTimestamp(Seg),
-- then apply the same before + same-part-of-day self-join as the discrete version.
WITH Step(TourId, Seg) AS (
SELECT TourId, unnest(segments(Tour))
FROM TempTour ),
DayPart AS (
SELECT *,
DayPart(TourId, StepNo, Name, Price, StartT, PartOfDay) AS (
SELECT TourId,
(startValue(Seg)->>'StepNo')::integer,
startValue(Seg)->>'Name',
startValue(Seg)->>'Price',
startTimestamp(Seg),
CASE
WHEN EXTRACT(HOUR FROM lower(AtTime)) BETWEEN 8 AND 11
THEN 'Morning'
WHEN EXTRACT(HOUR FROM lower(AtTime)) BETWEEN 12 AND 17
THEN 'Afternoon'
WHEN EXTRACT(HOUR FROM lower(AtTime)) BETWEEN 18 AND 23
THEN 'Evening'
WHEN EXTRACT(HOUR FROM startTimestamp(Seg)) BETWEEN 8 AND 11 THEN 'Morning'
WHEN EXTRACT(HOUR FROM startTimestamp(Seg)) BETWEEN 12 AND 17 THEN 'Afternoon'
WHEN EXTRACT(HOUR FROM startTimestamp(Seg)) BETWEEN 18 AND 23 THEN 'Evening'
ELSE 'Night'
END AS partOfDay
END
FROM Step )
...
-- Continue as the non-temporal above
-- I haven't found another way to write a temporal version of the above query
SELECT DISTINCT f.TourId, f.StepNo AS FirstStep, f.Name AS FirstName,
s.StepNo AS SecondStep, s.Name AS SecondName, f.PartOfDay
FROM DayPart f, DayPart s
WHERE f.TourId = s.TourId AND f.StartT < s.StartT AND
s.Price = 'Moderate' AND f.PartOfDay = s.PartOfDay
ORDER BY f.TourId;

/*
tourid | firststep | firstname | secondstep | secondname | partofday
--------+-----------+---------------+------------+------------------+-----------
9 | 1 | Musee d'Orsay | 2 | Le Petit Italien | Morning
*/

/*****************************************************************************/

Expand Down Expand Up @@ -490,7 +502,7 @@ WITH ModeratePrices(TourId, Tour, Location) AS (
WHERE atValue(Tour->>'Price', text 'Moderate') IS NOT NULL )
SELECT TourId, startValue(Tour->>'StepNo')::integer AS StepNo,
startValue(Tour->>'Name') AS StepName,
ST_Distance(startValue(m.Location), ST_Centroid(p.BufferGeom)) AS Distance
ST_Distance(startValue(m.Location), ST_Centroid(p.Geom)) AS Distance
FROM ModeratePrices m, PoI p
WHERE p.Name = 'Centre Pompidou' AND
ST_DWithin(valueAtTimestamp(m.Location, startTimestamp(Tour)), p.Geom, 1000)
Expand Down