You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求实现特定规则的SQL函数:生成带通配符的阈值间整数数组

Got it, let's build this SQL function step by step. The goal is to take two same-digit integers (lower and upper bounds) and return a compressed array where we use * as a wildcard to represent full ranges of consecutive numbers (like 941* for 9410-9419, 93* for 9300-9399) instead of listing every single number.

Approach

The core idea is to work backwards from the upper bound, checking for the largest possible range we can represent with a wildcard first. If we find a full range (where all numbers starting with a prefix fall between our bounds), we add that wildcard entry to our result and jump to the number right before the start of that range. If no such range exists, we just add the current number and decrement by 1.

Implementation (PostgreSQL PL/pgSQL)

Here's a function that does exactly this:

CREATE OR REPLACE FUNCTION compress_range(L bigint, U bigint)
RETURNS text[] AS $$
DECLARE
    digit_count integer;
    current_num bigint;
    result_array text[] := '{}'::text[];
    prefix text;
    range_start bigint;
    range_end bigint;
    wildcard_length integer;
    max_wildcard_len integer;
BEGIN
    -- Ensure lower bound <= upper bound (swap if needed)
    IF L > U THEN
        SELECT U, L INTO L, U;
    END IF;

    -- Validate both numbers have the same number of digits
    digit_count := length(L::text);
    IF length(U::text) != digit_count THEN
        RAISE EXCEPTION 'Both input numbers must have the same number of digits';
    END IF;

    current_num := U;

    WHILE current_num >= L LOOP
        max_wildcard_len := 0;

        -- Check for the longest possible wildcard range starting from largest possible length
        FOR wildcard_length IN REVERSE 1..digit_count-1 LOOP
            prefix := left(current_num::text, digit_count - wildcard_length);
            range_start := (prefix || repeat('0', wildcard_length))::bigint;
            range_end := (prefix || repeat('9', wildcard_length))::bigint;

            -- Check if the entire range fits within our bounds and ends at or before current number
            IF range_start >= L AND range_end <= current_num THEN
                max_wildcard_len := wildcard_length;
                EXIT; -- Found the longest valid wildcard, break the loop
            END IF;
        END LOOP;

        IF max_wildcard_len > 0 THEN
            -- Add the wildcard entry to results
            prefix := left(current_num::text, digit_count - max_wildcard_len);
            result_array := array_append(result_array, prefix || '*');
            -- Jump to the number right before the start of this range
            current_num := (prefix || repeat('0', max_wildcard_len))::bigint - 1;
        ELSE
            -- No valid wildcard range, add the single number
            result_array := array_append(result_array, current_num::text);
            current_num := current_num - 1;
        END IF;
    END LOOP;

    RETURN result_array;
END;
$$ LANGUAGE plpgsql;

How to Use It

Test it with your example input:

SELECT compress_range(3778, 9423);

This will return an array starting with 9423, 9422, 9421, 9420, then 941*, followed by 93*, 92*, ..., 38*, then 378*, 3779, 3778—exactly matching your expected output.

Key Notes

  • Input Validation: The function checks that both numbers have the same number of digits and swaps them if the lower bound is larger than the upper bound.
  • Wildcard Priority: We always check for the longest possible wildcard first, which ensures we compress as much as possible, minimizing the array length.
  • Flexibility: Works for any number of digits (as long as both inputs match), not just 4-digit numbers.

内容的提问来源于stack exchange,提问作者neetu saran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:54:02