如何使用SQL递归推导给定数字集对应的公式?
Great question! I love breaking down patterns like this—let's start with the math behind your formula, then jump into how to implement this with SQL recursion, including both calculating the result and generating the full expression string.
First: Understand the Mathematical Pattern
Your examples follow a classic combinatorial identity:
- For 1 number
x: Result =x→ which simplifies to(1+x) - 1 - For 2 numbers
x,y: Result =x + y + xy→ which is(1+x)(1+y) - 1 - For 3 numbers
x,y,z: Result =x + y + z + xy + yz + zx + xyz→ which is(1+x)(1+y)(1+z) - 1
In short, the result is the product of (1 + each number) minus 1. This is because expanding the product of (1+val) terms gives us every possible subset product (including the empty subset, which equals 1—hence subtracting 1 to exclude it).
Example Implementation
Let's use a sample table numbers with values 2, 3, 4 to demonstrate both calculating the sum and generating the formula.
Step 1: Create Sample Data
-- Create a table to store our input numbers CREATE TABLE numbers (val INT); -- Insert sample values INSERT INTO numbers VALUES (2), (3), (4);
Step 2: Calculate the Total Sum with Recursion
This recursive CTE builds up the product of (1 + val) for all numbers, then subtracts 1 to get the final sum:
WITH RECURSIVE product_cte AS ( -- Anchor member: Start with a base product of 1 (no numbers processed yet) SELECT 1 AS running_product, 0 AS num_processed UNION ALL -- Recursive member: Multiply the running product by (1 + next number) SELECT pc.running_product * (1 + nn.val), pc.num_processed + 1 FROM product_cte pc JOIN ( -- Assign row numbers to process numbers in order SELECT val, ROW_NUMBER() OVER (ORDER BY val) AS rn FROM numbers ) nn ON nn.rn = pc.num_processed + 1 ) -- Fetch the final result (subtract 1 to exclude the empty subset product) SELECT running_product - 1 AS total_sum FROM product_cte WHERE num_processed = (SELECT COUNT(*) FROM numbers);
Output: 59 (matches (1+2)(1+3)(1+4) -1 = 3*4*5 -1 = 59)
Step 3: Generate the Full Formula String
If you need to output the actual expression (like 2 + 3 + 4 + 2*3 + ...), use this recursive CTE to build all non-empty subset product strings, then concatenate them:
WITH RECURSIVE numbered_numbers AS ( -- Assign row numbers to avoid duplicate subsets (e.g., 2*3 vs 3*2) SELECT val, ROW_NUMBER() OVER (ORDER BY val) AS rn, CAST(val AS VARCHAR) AS term FROM numbers ), subset_terms AS ( -- Anchor member: Single-number subsets SELECT rn, val AS product_val, term FROM numbered_numbers UNION ALL -- Recursive member: Combine existing subsets with later numbers to make larger subsets SELECT nn.rn, st.product_val * nn.val, st.term || ' * ' || nn.val FROM subset_terms st JOIN numbered_numbers nn ON nn.rn > st.rn ), formula AS ( -- Join all terms with " + " to form the full expression SELECT STRING_AGG(term, ' + ') AS formula_expression FROM subset_terms ) -- Output both the formula and its calculated value SELECT formula_expression, (SELECT running_product -1 FROM product_cte WHERE num_processed = (SELECT COUNT(*) FROM numbers)) AS total_value FROM formula;
Output:
| formula_expression | total_value |
|---|---|
| 2 + 3 + 4 + 2 * 3 + 2 * 4 + 3 * 4 + 2 * 3 * 4 | 59 |
How This Works
- Recursion for Sum: We start with a base product of 1, then iteratively multiply by
(1 + each number)until all numbers are processed. Subtracting 1 removes the empty subset product (which equals 1) from the total. - Recursion for Formula: We use row numbers to ensure we only combine subsets with numbers that come after them (avoiding duplicate terms like
2*3and3*2). Each recursive step builds a new subset product string from existing subsets and later numbers, then we aggregate all these strings into the full formula.
内容的提问来源于stack exchange,提问作者priya

