is there any way to pivot rows to columns dynamica

2020-05-06 12:49发布

问题:

I need a way to display my data from rows to columns dynamically using sql. My row no. starts from 0 to N and I want to convert it to columns. I cannot use static column to match my requirement because the maximum no of rows changes every time depending on the policy required by the company. I have done researching but firebird has no pivot/transpose/cross-tab implementation (i might be wrong). Here are my tables

here is my client tables

here is my payable table

i need to display like this since there are many clients involve

as you can notice my client can have 0 to N payable.

Is there a way to implement it using firebird sql?

回答1:

We have encountered this situation in our environment with Firebird. Mark is correct you can't do dynamic pivot, but in our scenario needed that functionality. What we implemented was for our frontend to make a call to a stored procedure in Firebird which would "build" the SQL for the fixed pivot and then return the SQL and then the frontend would then execute the SQL. To the user it would look like a dynamic SQL.

In your specific case regular sql should suffice.

if you execute this from the front end this will return you a SQL statement.

with cte as (
Select DISTINCT loantype,
       'SUM(CASE loantype WHEN ''' || loantype || ''' then loanamt' || ' ELSE 0 END) ' CASE_STMT  from tblpayables
             )
    Select 'Select m.MEMBERID ,'
           || cast( List( cte.case_stmt  || replace(loantype,' ','')) as varchar(3000))
           ||' from tblmembers  m inner join tblpayables p on m.MEMBERID = p.MEMBERID group by m.MEMBERID'
    from cte

the query above will return this result (I formatted so it's more readable).

Select m.MEMBERID ,
       SUM(CASE loantype WHEN 'loan type 1' then loanamt ELSE 0 END) loantype1,
       SUM(CASE loantype WHEN 'loan type 2' then loanamt ELSE 0 END) loantype2,
       SUM(CASE loantype WHEN 'loan type 3' then loanamt ELSE 0 END) loantype3,
       SUM(CASE loantype WHEN 'loan type 4' then loanamt ELSE 0 END) loantype4
from tblmembers  m
inner join tblpayables p on m.MEMBERID = p.MEMBERID
group by m.MEMBERID

I had to remove the spaces within the column labels because Firebird didn't like spaces in the labels. But if you then execute the SQL it should work as you want. This will dynamically expand for each distinct loan types.



回答2:

You can't create a dynamic pivot using SQL in Firebird. You can achieve a fixed pivot with CASE WHEN, or - in Firebird 4 - with the FILTER clause, but dynamic pivots are not possible.

You will need to dynamically generate the necessary query, or query the data and transform it in your front-end.