mirror of
https://code.naskya.net/repos/ndqEd
synced 2025-01-26 22:17:50 +09:00
Simpler path selection in SQL transitive reduction
The transitive reduction query works by removing all the edges which aren't the only paths between their nodes, i.e. longer paths exist. The first step is to pick all the paths which include 2 or more edges. The initial code did that appending in-edges to all paths, which results with unnecessary duplicates and an INNER JOIN. Now, instead, just pick all the paths with length of more than 3 nodes. This is hopefully not just simpler, but also faster.
This commit is contained in:
parent
a41f111bee
commit
461283ba6e
1 changed files with 26 additions and 30 deletions
|
@ -58,11 +58,12 @@ import Database.Persist.Local.Sql.Orphan.Common
|
||||||
-- >
|
-- >
|
||||||
-- > EXCEPT
|
-- > EXCEPT
|
||||||
-- >
|
-- >
|
||||||
-- > SELECT e.*
|
-- > SELECT edge.*
|
||||||
-- > FROM edge AS pre
|
-- > FROM edge INNER JOIN temp
|
||||||
-- > INNER JOIN temp ON pre.dest = temp.path[1]
|
-- > ON edge.source = temp.path[1] AND
|
||||||
-- > INNER JOIN edge AS e ON e.source = pre.source AND e.dest = temp.id
|
-- > edge.dest = temp.id
|
||||||
-- > WHERE NOT temp.cycle
|
-- > WHERE array_length(temp.path, 1) > 2 AND
|
||||||
|
-- > NOT temp.cycle
|
||||||
trrSelect
|
trrSelect
|
||||||
:: ( MonadIO m
|
:: ( MonadIO m
|
||||||
, PersistEntityGraph node edge
|
, PersistEntityGraph node edge
|
||||||
|
@ -81,8 +82,6 @@ trrSelect proxy = do
|
||||||
tid = DBName "id"
|
tid = DBName "id"
|
||||||
tpath = DBName "path"
|
tpath = DBName "path"
|
||||||
tcycle = DBName "cycle"
|
tcycle = DBName "cycle"
|
||||||
edgeP = DBName "pre"
|
|
||||||
edgeE = DBName "e"
|
|
||||||
dbname = connEscapeName conn
|
dbname = connEscapeName conn
|
||||||
ecols = T.intercalate ", " $ entityColumnNames tEdge conn
|
ecols = T.intercalate ", " $ entityColumnNames tEdge conn
|
||||||
qecols name =
|
qecols name =
|
||||||
|
@ -121,14 +120,13 @@ trrSelect proxy = do
|
||||||
, " SELECT ", ecols
|
, " SELECT ", ecols
|
||||||
, " FROM ", dbname $ entityDB tEdge
|
, " FROM ", dbname $ entityDB tEdge
|
||||||
, " EXCEPT "
|
, " EXCEPT "
|
||||||
, " SELECT ", qecols edgeE
|
, " SELECT ", qecols $ entityDB tEdge
|
||||||
, " FROM ", dbname $ entityDB tEdge, " AS ", dbname edgeP
|
, " FROM ", entityDB tEdge <#> temp
|
||||||
, " INNER JOIN ", dbname temp
|
, " ON "
|
||||||
, " ON ", edgeP ^* fieldDB fwd, " = ", temp ^* tpath, "[1]"
|
, entityDB tEdge ^* fieldDB bwd, " = ", temp ^* tpath, "[1] AND "
|
||||||
, " INNER JOIN ", dbname $ entityDB tEdge, " AS ", dbname edgeE
|
, entityDB tEdge ^* fieldDB fwd, " = ", temp ^* tid
|
||||||
, " ON ", edgeE ^* fieldDB bwd, " = ", edgeP ^* fieldDB bwd
|
, " WHERE array_length(", temp ^* tpath, ", 1) > 2 AND NOT "
|
||||||
, " AND ", edgeE ^* fieldDB fwd, " = ", temp ^* tid
|
, temp ^* tcycle
|
||||||
, " WHERE NOT ", temp ^* tcycle
|
|
||||||
]
|
]
|
||||||
rawSql sql []
|
rawSql sql []
|
||||||
|
|
||||||
|
@ -148,11 +146,12 @@ trrSelect proxy = do
|
||||||
-- > )
|
-- > )
|
||||||
-- > DELETE FROM edge
|
-- > DELETE FROM edge
|
||||||
-- > WHERE id IN (
|
-- > WHERE id IN (
|
||||||
-- > SELECT e.id
|
-- > SELECT edge.id
|
||||||
-- > FROM edge AS pre
|
-- > FROM edge INNER JOIN temp
|
||||||
-- > INNER JOIN temp ON pre.dest = temp.path[1]
|
-- > ON edge.source = temp.path[1] AND
|
||||||
-- > INNER JOIN edge AS e ON e.source = pre.source AND e.dest = temp.id
|
-- > edge.dest = temp.id
|
||||||
-- > WHERE NOT temp.cycle
|
-- > WHERE array_length(temp.path, 1) > 2 AND
|
||||||
|
-- > NOT temp.cycle
|
||||||
-- > )
|
-- > )
|
||||||
trrApply
|
trrApply
|
||||||
:: ( MonadIO m
|
:: ( MonadIO m
|
||||||
|
@ -172,8 +171,6 @@ trrApply proxy = do
|
||||||
tid = DBName "id"
|
tid = DBName "id"
|
||||||
tpath = DBName "path"
|
tpath = DBName "path"
|
||||||
tcycle = DBName "cycle"
|
tcycle = DBName "cycle"
|
||||||
edgeP = DBName "pre"
|
|
||||||
edgeE = DBName "e"
|
|
||||||
dbname = connEscapeName conn
|
dbname = connEscapeName conn
|
||||||
t ^* f = dbname t <> "." <> dbname f
|
t ^* f = dbname t <> "." <> dbname f
|
||||||
t <#> s = dbname t <> " INNER JOIN " <> dbname s
|
t <#> s = dbname t <> " INNER JOIN " <> dbname s
|
||||||
|
@ -205,14 +202,13 @@ trrApply proxy = do
|
||||||
, sqlStep fwd bwd
|
, sqlStep fwd bwd
|
||||||
, " ) DELETE FROM ", dbname $ entityDB tEdge
|
, " ) DELETE FROM ", dbname $ entityDB tEdge
|
||||||
, " WHERE ", entityDB tEdge ^* fieldDB (entityId tEdge), " IN ("
|
, " WHERE ", entityDB tEdge ^* fieldDB (entityId tEdge), " IN ("
|
||||||
, " SELECT ", edgeE ^* fieldDB (entityId tEdge)
|
, " SELECT ", entityDB tEdge ^* fieldDB (entityId tEdge)
|
||||||
, " FROM ", dbname $ entityDB tEdge, " AS ", dbname edgeP
|
, " FROM ", entityDB tEdge <#> temp
|
||||||
, " INNER JOIN ", dbname temp
|
, " ON "
|
||||||
, " ON ", edgeP ^* fieldDB fwd, " = ", temp ^* tpath, "[1]"
|
, entityDB tEdge ^* fieldDB bwd, " = ", temp ^* tpath
|
||||||
, " INNER JOIN ", dbname $ entityDB tEdge, " AS ", dbname edgeE
|
, "[1] AND ", entityDB tEdge ^* fieldDB fwd, " = ", temp ^* tid
|
||||||
, " ON ", edgeE ^* fieldDB bwd, " = ", edgeP ^* fieldDB bwd
|
, " WHERE array_length(", temp ^* tpath, ", 1) > 2 AND NOT "
|
||||||
, " AND ", edgeE ^* fieldDB fwd, " = ", temp ^* tid
|
, temp ^* tcycle
|
||||||
, " WHERE NOT ", temp ^* tcycle
|
|
||||||
, " )"
|
, " )"
|
||||||
]
|
]
|
||||||
rawExecuteCount sql []
|
rawExecuteCount sql []
|
||||||
|
|
Loading…
Add table
Reference in a new issue