HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

How can I calculate all grouping permutations of an input string in SQL?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
canallgroupingsqlinputcalculatehowstringpermutations

Problem

Given an input like "ABC" generate a query that calculates all potential splits of 0 or more of the given string,

Desired output,

A   B   C
A   BC
AB  C
ABC


Given an input like "ABCD"

A    B   C    D
A    BC  D
A    B   CD
AB   C   D
A    BCD
AB   CD
ABC  D
ABCD


Not all that concerned with how output is formed, array, rows, json, etc. More looking for discrete list of all permutations of grouping.

Solution

I guess that is just a challenge for fun, but here is my solution:

WITH s(s) AS (VALUES ('ABCD'))
SELECT substr(s, 1, 1) ||
       string_agg(
          CASE WHEN i & (2::numeric ^ p)::bigint = 0 THEN '' ELSE ' ' END ||
          substr(s, p + 2, 1),
          ''
       )
FROM s
   CROSS JOIN generate_series(0, (2::numeric ^ (length(s) - 1) - 1)::bigint) AS i
   CROSS JOIN generate_series(0, length(s) - 2) AS p
GROUP BY s, i;

 ?column? 
══════════
 A BC D
 AB C D
 ABCD
 ABC D
 A B CD
 AB CD
 A B C D
 A BCD
(8 rows)


The idea is to get the binary numbers from 0 to 2 ^ (length - 1) - 1 and interpolate spaces wherever there is a 1. So 101 (decimal 5) would become A BC D.

Code Snippets

WITH s(s) AS (VALUES ('ABCD'))
SELECT substr(s, 1, 1) ||
       string_agg(
          CASE WHEN i & (2::numeric ^ p)::bigint = 0 THEN '' ELSE ' ' END ||
          substr(s, p + 2, 1),
          ''
       )
FROM s
   CROSS JOIN generate_series(0, (2::numeric ^ (length(s) - 1) - 1)::bigint) AS i
   CROSS JOIN generate_series(0, length(s) - 2) AS p
GROUP BY s, i;

 ?column? 
══════════
 A BC D
 AB C D
 ABCD
 ABC D
 A B CD
 AB CD
 A B C D
 A BCD
(8 rows)

Context

StackExchange Database Administrators Q#302389, answer score: 9

Revisions (0)

No revisions yet.