1

I have a table that looks like this:


| Scenario| Date   | System | Result |
| ------- | ------ | ------ | ------ |
| Proj1   | 07-01  | A      | PASS   |
| Proj1   | 07-01  | B      | PASS   |
| Proj1   | 07-01  | C      | PASS   |
| Proj1   | 07-01  | D      | PASS   |
| Proj1   | 07-02  | A      | FAIL   |
| Proj1   | 07-02  | B      | FAIL   |
| Proj1   | 07-02  | C      | FAIL   |
| Proj1   | 07-02  | D      | FAIL   |
| Proj2   | 07-01  | E      | PASS   |
| Proj2   | 07-01  | F      | FAIL   |
| Proj2   | 07-02  | E      | PASS   |
| Proj2   | 07-02  | F      | PASS   |

I rearranged it to this:

| Scenario| Date | System1 | System2 | System3 | System4| Overall|
| ------- | ---- | ------- | ------- | ------- | -------|--------|
| Proj1   | 07-01| A-PASS  | B-PASS  | C-PASS  | D-PASS |PASS    |
| Proj1   | 07-02| A-FAIL  | B-FAIL  | C-FAIL  | D-FAIL |FAIL    |
| Proj2   | 07-01| E-PASS  | F-FAIL  |         |        |FAIL    |
| Proj2   | 07-02| E-PASS  | F-PASS  |         |        |PASS    |

Right now, the order of the systems is alphabetical but I created a mapping table in which it orders the priority of the systems

|Scenario|System | Priority|
|------- |-------| --------|
|Proj1   |A      | 2       |
|Proj1   |B      | 3       |
|Proj1   |C      | 1       |
|Proj1   |D      | 4       |
|Proj2   |E      | 1       |
|Proj2   |F      | 2       |

Is there a way to adjust the order such that it reflects the priority and is as such:

| Scenario| Date | System1 | System2 | System3 | System4| Overall|
| ------- | ---- | ------- | ------- | ------- | -------|--------|
| Proj1   | 07-01| C-PASS  | A-PASS  | B-PASS  | D-PASS |PASS    |
| Proj1   | 07-02| C-FAIL  | A-FAIL  | B-FAIL  | D-FAIL |FAIL    |
| Proj2   | 07-01| E-PASS  | F-FAIL  |         |        |FAIL    |
| Proj2   | 07-02| E-PASS  | F-PASS  |         |        |PASS    |

2
  • Instead of producing 4 columns, maybe you could produce a single one with comma-separated values. Commented Aug 2, 2022 at 15:27
  • I considered that, but I from a aesthetic perspective, I think it looked clearer separating the columns. Thanks for the suggestion! Commented Aug 2, 2022 at 15:34

1 Answer 1

1

You may find the count of all systems for a specific (Date,Scenario) by using Count(*) over (Partition By Scenario,Date), and the count of only passed systems for that (Date,Scenario) by using Aggregate Filter as the following, count(*) filter (where Result='PASS') over (Partition By Scenario,Date).

Then compare the two counts, if they are equal then set the overall result as PASS.

Consider the following:

Create Or Replace Function pvt()
    RETURNS void
    LANGUAGE 'plpgsql'
As $body$
declare
    sqlColumn varchar;
    qr varchar;
    columnlist varchar;
Begin
sqlColumn= 'select distinct D.sys_cat from (select Row_Number() Over (Partition By Scenario,Date Order By System) as sys_cat From run) D order by D.sys_cat;';
qr='prepare pvtstmt AS Select D.Scenario,D.Date,';

For columnlist In EXECUTE sqlColumn  
   Loop
      qr=qr || 'Max(Case When sys_cat=' || columnlist || ' Then (System || ''_'' || Result) Else '''' End) As System' ||  columnlist ||  ' , ';
   END LOOP;
   
   --qr=substr(qr, 0, length(qr) - 1);
   qr=qr|| 'case when D.tc= D.pc then ''PASS'' else ''FAIL'' end as overall ';
   qr=qr || 'From (select *, Count(*) over (Partition By Scenario,Date) tc,'||
   ' count(*) filter (where Result=''PASS'') over (Partition By Scenario,Date) pc,'||
   '  Row_Number() Over (Partition By Scenario,Date Order By System) as sys_cat From run) D Where D.Scenario =' 
   || '''Proj1'' Group By D.Scenario,D.Date,overall Order By D.Scenario,D.Date';
   
Deallocate All;
EXECUTE qr;
End;
$body$

See a demo from db<>fiddle.

For the second required output, you may use the following function:

Create Or Replace Function pvt(qr_selector int, Scenario_selector varchar default 'all')
    RETURNS void
    LANGUAGE plpgsql AS
$body$
declare
    sqlColumn varchar;
    qr varchar; qr2 varchar;
    columnlist varchar;
Begin
  sqlColumn= 'select distinct D.sys_cat from (select Row_Number() Over (Partition By Scenario,Date Order By System) as sys_cat From run) D order by D.sys_cat;';
  qr='Select D.Scenario,D.Date,';

  For columnlist In EXECUTE sqlColumn  
   Loop
      qr=qr || 'Max(Case When sys_cat=' || columnlist || ' Then (System || ''_'' || Result) Else '''' End) As System' ||  columnlist ||  ' , ';
   END LOOP;
   
   --qr=substr(qr, 0, length(qr) - 1);
  qr=qr|| 'case when D.tc= D.pc then ''PASS'' else ''FAIL'' end as overall ';
  qr=qr || 'From (select *, Count(*) over (Partition By Scenario,Date) tc,'||
  ' count(*) filter (where Result=''PASS'') over (Partition By Scenario,Date) pc,'||
  '  Row_Number() Over (Partition By Scenario,Date Order By System) as sys_cat From run) D ';
   
  if Scenario_selector='all' then
    qr=qr || ' Group By D.Scenario,D.Date,overall Order By D.Scenario,D.Date';
  else
    qr=qr || 'Where D.Scenario =''' || Scenario_selector || ''' Group By D.Scenario,D.Date,overall Order By D.Scenario,D.Date';
  end if;
   
  qr2='with cte as (' || qr || ') Select date, count(*) filter (where overall=''PASS'') as Num_Of_Passes,' ||
  'count(*) filter (where overall=''FAIL'') as Num_Of_Fails ' ||
  'from cte group by date;';
   
  Deallocate All;

  if qr_selector = 1 then
   EXECUTE 'prepare pvtstmt AS ' || qr;
  else
   EXECUTE 'prepare pvtstmt AS ' || qr2;
  end if;
End;
$body$

The first parameter in the function qr_selector lets you to choose what query to execute, 1 for the first output, 2 for the second output. The second parameter Scenario_selector lets you to filter the Scenario values, where the default value is 'all'.

i.e. to select the first output result for all Scenario values use Select pvt(1);, and to select the second output result for Scenario = 'Proj1' use Select pvt(2,'Proj1');

See a demo from db<>fiddle.

Sign up to request clarification or add additional context in comments.

10 Comments

Wow - this is amazing. Thank you so much, this is all starting to make sense. Do you know if there is a way to query the results of this table? I was going to create a graph where I SUM when overall = "PASS" and overall = "FAIL" to show the progression of pass/fail on each day.
Can you edit the question and post a sample of the required output including that sums.
Sure, just edited it!
The answer has been updated with the new requirement, also with more dynamic function.
Wow, the idea of adding a second parameter was very cool. I was thinking of maybe creating a different function, this is much more concise. Also, I have edited the question and was wondering if you knew if there was a way to adjust the order of the systems? I was thinking of creating some parameter within the loop but was not sure if that is possible?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.