Basically you can use such a static solution containing conditional aggregation logic
SELECT id,
MAX(CASE WHEN rn = 1 THEN State_Assign END) AS sa1,
MAX(CASE WHEN rn = 2 THEN State_Assign END) AS sa2,
.......
.......
COUNT(*) AS total
FROM (SELECT s.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY 0) AS rn
FROM sampledata s)
GROUP BY id
ORDER BY id
A stored function might be created in order to generate select statement which will produce dynamical results depending on the current values of the table such as
CREATE OR REPLACE FUNCTION Get_Pivoted_States RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_cols VARCHAR2(32767);
BEGIN
SELECT LISTAGG('MAX(CASE WHEN rn = '||rn||' THEN State_Assign END) AS sa'||rn ,',')
WITHIN GROUP (ORDER BY 0)
INTO v_cols
FROM (SELECT DISTINCT ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS rn
FROM sampledata);
v_sql :='SELECT id,
'|| v_cols ||',
COUNT(*) AS total
FROM (SELECT s.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY 0) AS rn
FROM sampledata s)
GROUP BY id
ORDER BY id';
OPEN v_recordset FOR v_sql;
DBMS_OUTPUT.PUT_LINE(v_sql);
RETURN v_recordset;
END;
/
The function might be invoked from the SQL Developer's console as
SQL> DECLARE
result SYS_REFCURSOR;
BEGIN
:result := Get_Pivoted_States;
END;
/
SQL> PRINT result;