Skip to content

Instantly share code, notes, and snippets.

@estum
Last active June 5, 2020 20:13
Show Gist options
  • Save estum/0439def37ae45d4e08897755e754613e to your computer and use it in GitHub Desktop.
Save estum/0439def37ae45d4e08897755e754613e to your computer and use it in GitHub Desktop.
PostgreSQL: recursively shift rows in order using modifier
-- +--------+-------+-------+
-- | init | mod | exp |
-- |--------+-------+-------|
-- | 6 | -1 | 5 |
-- | 5 | 0 | 4 |
-- | 4 | 1 | 6 |
-- | 3 | 0 | 3 |
-- | 2 | -1 | 1 |
-- | 1 | 0 | 2 |
-- +--------+-------+-------+
WITH v(init, mod, exp) AS (
VALUES (6, -1, 5), (5, 0, 4), (4, 1, 6), (3, 0, 3), (2, -1, 1), (1, 0, 2)
), sort_r(init, pos) AS (
WITH RECURSIVE t(init, mod, exp, pos, d) AS (
SELECT *, init, 1 FROM v
UNION ALL
SELECT t.init,
t.mod - (lag(t.mod) OVER w),
t.exp,
t.pos + t.mod,
t.d + 1
FROM t
WHERE t.mod <> 0
WINDOW w AS (ORDER BY t.pos DESC ROWS 1 PRECEDING)
)
SELECT init, row_number() OVER (ORDER BY pos ASC)
FROM (SELECT * FROM t WHERE d = (SELECT max(d) FROM t t2 WHERE t2.init = t.init)) sub
)
SELECT sort_r.*, v.exp FROM sort_r, v WHERE v.init = sort_r.init ORDER BY pos DESC;
-- +--------+-------+-------+
-- | init | pos | exp |
-- |--------+-------+-------|
-- | 4 | 6 | 6 |
-- | 6 | 5 | 5 |
-- | 5 | 4 | 4 |
-- | 3 | 3 | 3 |
-- | 1 | 2 | 2 |
-- | 2 | 1 | 1 |
-- +--------+-------+-------+
--
-- \ 0 /
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment