Link to home
Start Free TrialLog in
Avatar of hc2342uhxx3vw36x96hq
hc2342uhxx3vw36x96hqFlag for United States of America

asked on

Detecting all distinct characters used in all records of a column present in an Oracle table

Please, could you help me to write a stored function that, acting on a COLUMN, will give in output the different characters contained in every record with reference to that column.

In example:

If you have the table PIPPO containing the column ALPHA with these values:

ABCDE
FGHIJ
KLMNOABCDE
FGHIJ44433
1234567

... launching the SELECT:

SELECT MAGIC_FUNCTION (ALPHA) from PIPPO;

... will produce:

1234567ABCDEFGHIJKLMNO
ASKER CERTIFIED SOLUTION
Avatar of ajexpert
ajexpert
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of hc2342uhxx3vw36x96hq

ASKER

OK ;-)
Avatar of Sean Stuber
Sean Stuber

I know this question is long over, but it looked like an interesting question, so I had to take a crack at it.  :)

Here's my approach.  I created an aggregate function called "distinctagg"  it works just like other aggregates and is pretty quick.

This took about 2 seconds on my laptop with 74302 objects in dba_objects

select distinctagg(object_name),count(*) from dba_objects

The sorting and distinct search I used is basically just a simple insertion sort with duplicates removed.


CREATE OR REPLACE TYPE distinct_chars_type
AS
    OBJECT(
        v_result VARCHAR2(4000),
        MEMBER FUNCTION distinct_chars(p_unique IN VARCHAR2, p_new IN VARCHAR2)
            RETURN VARCHAR2
            DETERMINISTIC,
        STATIC FUNCTION odciaggregateinitialize(p_sctx IN OUT distinct_chars_type)
            RETURN NUMBER,
        MEMBER FUNCTION odciaggregateiterate(self IN OUT distinct_chars_type, p_value IN VARCHAR2)
            RETURN NUMBER,
        MEMBER FUNCTION odciaggregateterminate(
            self            IN     distinct_chars_type,
            p_returnvalue      OUT VARCHAR2,
            p_flags         IN     NUMBER
        )
            RETURN NUMBER,
        MEMBER FUNCTION odciaggregatemerge(
            self     IN OUT distinct_chars_type,
            p_ctx2   IN     distinct_chars_type
        )
            RETURN NUMBER
    );
/
 
CREATE OR REPLACE TYPE BODY distinct_chars_type
IS
    MEMBER FUNCTION distinct_chars(p_unique IN VARCHAR2, p_new IN VARCHAR2)
        RETURN VARCHAR2
        DETERMINISTIC
    IS
        v_temp    VARCHAR2(32767) := NULL;
        v_index   INTEGER;
        v_char    CHAR(1);
    BEGIN
        v_temp   := p_unique;
 
        FOR i IN 1 .. NVL(LENGTH(p_new), 0)
        LOOP
            v_char   := SUBSTR(p_new, i, 1);
 
            IF NVL(INSTR(v_temp, v_char), 0) = 0
            THEN
                v_index   := 1;
 
                WHILE v_index <= NVL(LENGTH(v_temp), 0)
                LOOP
                    IF v_char < SUBSTR(v_temp, v_index, 1)
                    THEN
                        v_temp   :=
                            SUBSTR(v_temp, 1, v_index - 1) || v_char || SUBSTR(v_temp, v_index);
                        EXIT;
                    END IF;
 
                    v_index   := v_index + 1;
                END LOOP;
 
                IF v_index > NVL(LENGTH(v_temp), 0)
                THEN
                    v_temp   := v_temp || v_char;
                END IF;
            END IF;
        END LOOP;
 
        RETURN v_temp;
    END distinct_chars;
 
 
    STATIC FUNCTION odciaggregateinitialize(p_sctx IN OUT distinct_chars_type)
        RETURN NUMBER
    IS
    BEGIN
        p_sctx   := distinct_chars_type(NULL);
        RETURN odciconst.success;
    END odciaggregateinitialize;
 
    MEMBER FUNCTION odciaggregateiterate(self IN OUT distinct_chars_type, p_value IN VARCHAR2)
        RETURN NUMBER
    IS
    BEGIN
        self.v_result   := distinct_chars(self.v_result, p_value);
        RETURN odciconst.success;
    END odciaggregateiterate;
 
    MEMBER FUNCTION odciaggregateterminate(
        self          IN     distinct_chars_type,
        p_returnvalue      OUT VARCHAR2,
        p_flags         IN     NUMBER
    )
        RETURN NUMBER
    IS
    BEGIN
        p_returnvalue   := self.v_result;
        RETURN odciconst.success;
    END odciaggregateterminate;
 
    MEMBER FUNCTION odciaggregatemerge(
        self   IN OUT distinct_chars_type,
        p_ctx2   IN     distinct_chars_type
    )
        RETURN NUMBER
    IS
    BEGIN
        self.v_result   := distinct_chars(self.v_result, p_ctx2.v_result);
        RETURN odciconst.success;
    END odciaggregatemerge;
END;
/
 
 
CREATE OR REPLACE FUNCTION distinctagg(p_input VARCHAR2)
    RETURN VARCHAR2
    PARALLEL_ENABLE
    AGGREGATE USING distinct_chars_type;
/

Open in new window