Not to sound like a broken record, but…a few disclaimers:
- This is the fun stuff…that voids your warranty. Not that you have to tell Oracle that you poke around here, but if you do, they will blame anything and everything that’s wrong on you for being in there.
- The content here has been tested and validated against 11.1.2.3.500 and 11.1.2.4.
- The content here has been tested and validated against Microsoft SQL Server and Oracle 11g.
- The content here is based on the Vision sample application.
- The content here is totally unsupported by Oracle (in case you missed the first bullet).
We’ve finally made it to the last part in our series on the HSP_MEMBER table (and all of the many associated tables)! In this post, we’ll take everything that we’ve learned and combine it to get a full extract of a single custom dimension for a single plan type. In our SQL Server query, this is a pretty straight forward operation. We simply combine the queries from the prior five parts of this series.
SQL Server:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155SELECTo.OBJECT_NAME AS MEMBER_NAME,op.OBJECT_NAME AS PARENT_NAME,a1.ALIAS_NAME AS ALIAS_DEFAULT,a2.ALIAS_NAME AS ALIAS_ENGLISH,REPLACE(REPLACE(REPLACE((SELECTou.UDA_VALUE AS UDAFROMHSP_MEMBER_TO_UDA uINNER JOINHSP_UDA ou ON ou.UDA_ID = u.UDA_IDWHEREu.MEMBER_ID = m.MEMBER_ID FOR XML Raw), '"/><row UDA="', ', '), '<row UDA="', ''), '"/>', '' )AS UDA,CASE m.DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic'END AS DATA_STORAGE,CASE m.DATA_TYPEWHEN 0 THEN 'Unspecified'WHEN 1 THEN 'Currency'WHEN 2 THEN 'Non-currency'WHEN 3 THEN 'Percentage'WHEN 4 THEN 'Enum'WHEN 5 THEN 'Date'WHEN 6 THEN 'Text'ELSE 'Unspecified'END AS DATA_TYPE,CASE WHEN m.USED_IN & 1 = 1 THENCASEWHEN m.CONSOL_OP & 6 = 6 THEN '^'WHEN m.CONSOL_OP & 5 = 5 THEN '~'WHEN m.CONSOL_OP & 4 = 4 THEN '%'WHEN m.CONSOL_OP & 3 = 3 THEN '/'WHEN m.CONSOL_OP & 2 = 2 THEN '*'WHEN m.CONSOL_OP & 1 = 1 THEN '-'ELSE '+' ENDELSENULLEND AS PLAN1_CONSOL_OP,CASE WHEN mfp1.FORMULA IS NULL THEN mfpd.FORMULA ELSE mfp1.FORMULA END AS PLAN1_FORMULA,CASE WHEN mfp1.DATA_STORAGE IS NULL THEN mfpd.DATA_STORAGE ELSE mfp1.DATA_STORAGE END AS PLAN1_DATA_STORAGE,CASE WHEN mfp1.SOLVE_ORDER IS NULL THEN mfpd.SOLVE_ORDER ELSE mfp1.SOLVE_ORDER END AS PLAN1_SOLVE_ORDER,at.ATTRIBUTE_NAME AS ATTRIBUTE_TEXT,ab.ATTRIBUTE_NAME AS ATTRIBUTE_BOOLEANFROMHSP_MEMBER mINNER JOINHSP_OBJECT o ON m.MEMBER_ID = o.OBJECT_IDINNER JOINHSP_OBJECT op ON o.PARENT_ID = op.OBJECT_IDINNER JOINHSP_OBJECT od ON m.DIM_ID = od.OBJECT_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'Default')a1 ON m.MEMBER_ID = a1.MEMBER_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'English')a2 ON m.MEMBER_ID = a2.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Default') mfpd ON m.MEMBER_ID = mfpd.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Plan1') mfp1 ON m.MEMBER_ID = mfp1.MEMBER_IDLEFT JOIN(SELECTm.MEMBER_ID,amo.OBJECT_NAME AS ATTRIBUTE_NAMEFROMHSP_MEMBER mINNER JOINHSP_MEMBER_TO_ATTRIBUTE mta ON m.MEMBER_ID = mta.MEMBER_IDINNER JOINHSP_OBJECT ado ON mta.ATTR_ID = ado.OBJECT_IDINNER JOINHSP_OBJECT amo ON mta.ATTR_MEM_ID = amo.OBJECT_IDWHEREado.OBJECT_NAME = 'AttrText') at ON m.MEMBER_ID = at.MEMBER_IDLEFT JOIN(SELECTm.MEMBER_ID,amo.OBJECT_NAME AS ATTRIBUTE_NAMEFROMHSP_MEMBER mINNER JOINHSP_MEMBER_TO_ATTRIBUTE mta ON m.MEMBER_ID = mta.MEMBER_IDINNER JOINHSP_OBJECT ado ON mta.ATTR_ID = ado.OBJECT_IDINNER JOINHSP_OBJECT amo ON mta.ATTR_MEM_ID = amo.OBJECT_IDWHEREado.OBJECT_NAME = 'AttrBoolean') ab ON m.MEMBER_ID = ab.MEMBER_IDWHEREod.OBJECT_NAME = 'Product'
It makes for a long query…but effective. This query will give us all of our properties for our first plan type. And here are the results:
So SQL Server wasn’t too bad. How about Oracle? Well…that’s a different story. There are two ways to approach this query on the Oracle side. Option 1: combine all of the queries like we did in SQL Server. Sounds easy enough until you remember back to Part 3 of our series where we first used the LISTAGG function. That function makes this process a pain. Instead of just combining the queries together, we have to add everything to our group by as well. Here it is for fun:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147SELECTo.OBJECT_NAME AS MEMBER_NAME,op.OBJECT_NAME AS PARENT_NAME,a1.ALIAS_NAME AS ALIAS_DEFAULT,a2.ALIAS_NAME AS ALIAS_ENGLISH,LISTAGG(UDA_VALUE,', ') WITHIN GROUP (ORDER BY UDA_VALUE) "UDA LIST",CASE m.DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic'END AS DATA_STORAGE,CASE m.DATA_TYPEWHEN 0 THEN 'Unspecified'WHEN 1 THEN 'Currency'WHEN 2 THEN 'Non-currency'WHEN 3 THEN 'Percentage'WHEN 4 THEN 'Enum'WHEN 5 THEN 'Date'WHEN 6 THEN 'Text'ELSE 'Unspecified'END AS DATA_TYPE,CASE WHEN BITAND(m.USED_IN,1) = 1 THENCASEWHEN BITAND(m.CONSOL_OP,6) = 6 THEN '^'WHEN BITAND(m.CONSOL_OP,5) = 5 THEN '~'WHEN BITAND(m.CONSOL_OP,4) = 4 THEN '%'WHEN BITAND(m.CONSOL_OP,3) = 3 THEN '/'WHEN BITAND(m.CONSOL_OP,2) = 2 THEN '*'WHEN BITAND(m.CONSOL_OP,1) = 1 THEN '-'ELSE '+' ENDELSENULLEND AS PLAN1_CONSOL_OP,dbms_lob.substr(CASE WHEN mfp1.FORMULA IS NULL THEN mfpd.FORMULA ELSE mfp1.FORMULA END,4000,1) AS PLAN1_FORMULA,CASE WHEN mfp1.DATA_STORAGE IS NULL THEN mfpd.DATA_STORAGE ELSE mfp1.DATA_STORAGE END AS PLAN1_DATA_STORAGE,CASE WHEN mfp1.SOLVE_ORDER IS NULL THEN mfpd.SOLVE_ORDER ELSE mfp1.SOLVE_ORDER END AS PLAN1_SOLVE_ORDERFROMHSP_MEMBER mINNER JOINHSP_OBJECT o ON m.MEMBER_ID = o.OBJECT_IDINNER JOINHSP_OBJECT op ON o.PARENT_ID = op.OBJECT_IDINNER JOINHSP_OBJECT od ON m.DIM_ID = od.OBJECT_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'Default')a1 ON m.MEMBER_ID = a1.MEMBER_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'English')a2 ON m.MEMBER_ID = a2.MEMBER_IDLEFT JOIN( SELECTUDA_VALUE,MEMBER_IDFROMHSP_MEMBER_TO_UDA muINNER JOINHSP_UDA u ON mu.UDA_ID = u.UDA_ID) mu ON m.MEMBER_ID = mu.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME FROM DUAL UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Default') mfpd ON m.MEMBER_ID = mfpd.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME FROM DUAL UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Plan1') mfp1 ON m.MEMBER_ID = mfp1.MEMBER_IDWHEREod.OBJECT_NAME = 'Product'GROUP BYo.OBJECT_NAME,op.OBJECT_NAME,od.OBJECT_NAME,a1.ALIAS_NAME,a2.ALIAS_NAME,m.DATA_STORAGE,m.DATA_TYPE,CASE WHEN BITAND(m.USED_IN,1) = 1 THENCASEWHEN BITAND(m.CONSOL_OP,6) = 6 THEN '^'WHEN BITAND(m.CONSOL_OP,5) = 5 THEN '~'WHEN BITAND(m.CONSOL_OP,4) = 4 THEN '%'WHEN BITAND(m.CONSOL_OP,3) = 3 THEN '/'WHEN BITAND(m.CONSOL_OP,2) = 2 THEN '*'WHEN BITAND(m.CONSOL_OP,1) = 1 THEN '-'ELSE '+' ENDELSENULLEND,dbms_lob.substr(CASE WHEN mfp1.FORMULA IS NULL THEN mfpd.FORMULA ELSE mfp1.FORMULA END,4000,1),CASE WHEN mfp1.DATA_STORAGE IS NULL THEN mfpd.DATA_STORAGE ELSE mfp1.DATA_STORAGE END,CASE WHEN mfp1.SOLVE_ORDER IS NULL THEN mfpd.SOLVE_ORDER ELSE mfp1.SOLVE_ORDER END
It’s ugly, but it works. There was a problem with just adding everything to the GROUP BY. Member formulas are of type CLOB which of course can not be used in a GROUP BY. So what do we do? We instead use a substring function to convert the CLOB to a 4,000 character VARCHAR. This works great…assuming you don’t have any large formulas. So this isn’t a great solution.
So what do we do? Option B. We take a step back and place our LISTAGG function into its own sub-query. This let’s us move the group by to a very small place and still reference our member ID. Here it is:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121SELECTo.OBJECT_NAME AS MEMBER_NAME,op.OBJECT_NAME AS PARENT_NAME,a1.ALIAS_NAME AS ALIAS_DEFAULT,a2.ALIAS_NAME AS ALIAS_ENGLISH,( SELECT LISTAGG(UDA_VALUE,', ') WITHIN GROUP (ORDER BY UDA_VALUE) "UDA_LIST" FROM (SELECTUDA_VALUE,MEMBER_IDFROMHSP_MEMBER_TO_UDA muINNER JOINHSP_UDA u ON mu.UDA_ID = u.UDA_ID) muda WHERE muda.MEMBER_ID = m.MEMBER_ID) AS UDA,CASE m.DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic'END AS DATA_STORAGE,CASE m.DATA_TYPEWHEN 0 THEN 'Unspecified'WHEN 1 THEN 'Currency'WHEN 2 THEN 'Non-currency'WHEN 3 THEN 'Percentage'WHEN 4 THEN 'Enum'WHEN 5 THEN 'Date'WHEN 6 THEN 'Text'ELSE 'Unspecified'END AS DATA_TYPE,CASE WHEN BITAND(m.USED_IN,1) = 1 THENCASEWHEN BITAND(m.CONSOL_OP,6) = 6 THEN '^'WHEN BITAND(m.CONSOL_OP,5) = 5 THEN '~'WHEN BITAND(m.CONSOL_OP,4) = 4 THEN '%'WHEN BITAND(m.CONSOL_OP,3) = 3 THEN '/'WHEN BITAND(m.CONSOL_OP,2) = 2 THEN '*'WHEN BITAND(m.CONSOL_OP,1) = 1 THEN '-'ELSE '+' ENDELSENULLEND AS PLAN1_CONSOL_OP,CASE WHEN mfp1.FORMULA IS NULL THEN mfpd.FORMULA ELSE mfp1.FORMULA END AS PLAN1_FORMULA,CASE WHEN mfp1.DATA_STORAGE IS NULL THEN mfpd.DATA_STORAGE ELSE mfp1.DATA_STORAGE END AS PLAN1_DATA_STORAGE,CASE WHEN mfp1.SOLVE_ORDER IS NULL THEN mfpd.SOLVE_ORDER ELSE mfp1.SOLVE_ORDER END AS PLAN1_SOLVE_ORDERFROMHSP_MEMBER mINNER JOINHSP_OBJECT o ON m.MEMBER_ID = o.OBJECT_IDINNER JOINHSP_OBJECT op ON o.PARENT_ID = op.OBJECT_IDINNER JOINHSP_OBJECT od ON m.DIM_ID = od.OBJECT_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'Default')a1 ON m.MEMBER_ID = a1.MEMBER_IDLEFT JOIN( SELECToa.OBJECT_NAME AS ALIAS_NAME,a.MEMBER_IDFROMHSP_ALIAS aINNER JOINHSP_OBJECT oa ON a.ALIAS_ID = oa.OBJECT_IDINNER JOINHSP_OBJECT oat ON a.ALIASTBL_ID = oat.OBJECT_IDWHEREoat.OBJECT_NAME = 'English')a2 ON m.MEMBER_ID = a2.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME FROM DUAL UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Default') mfpd ON m.MEMBER_ID = mfpd.MEMBER_IDLEFT JOIN(SELECTMEMBER_ID,mf.PLAN_TYPE,CASE DATA_STORAGEWHEN 0 THEN 'Store Data'WHEN 1 THEN 'Never Share'WHEN 2 THEN 'Label Only'WHEN 3 THEN 'Shared Member'WHEN 4 THEN 'Dynamic Calc and Store'WHEN 5 THEN 'Dynamic' END AS DATA_STORAGE,SOLVE_ORDER,FORMULAFROMHSP_MEMBER_FORMULA mfLEFT JOIN(SELECT 0 AS PLAN_TYPE,'Default' AS TYPE_NAME FROM DUAL UNION ALLSELECT PLAN_TYPE,TYPE_NAME FROM HSP_PLAN_TYPE) p ON mf.PLAN_TYPE = p.PLAN_TYPEWHEREp.TYPE_NAME = 'Plan1') mfp1 ON m.MEMBER_ID = mfp1.MEMBER_IDWHEREod.OBJECT_NAME = 'Product'
This makes for a much shorter and less complex query. Well, mildly less complex as this requires not just a sub-query, but a nested sub-query. With either query, whether you choose the complex query with the big group by or the far simpler query with the nested sub-query, the results are the same:
And so the series on the HSP_MEMBER table (and all the other tables related) ends. But wait, there are more properties missing? The account dimension has more? The entity dimension has more? Tune in for yet another series, this time on the built-in dimensions.