Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQL सर्वर - जटिल गतिशील पिवट कॉलम

आपको यहां थोड़ी गड़बड़ी मिली है क्योंकि आपके पास अलग-अलग संरचनाओं में दो टेबल हैं और आप कई कॉलम पिवट करना चाहते हैं। तर्क को सही करने के लिए मैं पहले आपकी क्वेरी का एक स्थिर संस्करण लिखना शुरू करूंगा, फिर एक गतिशील संस्करण लिखने की प्रक्रिया से गुजरूंगा।

चूँकि आप अनेक स्तंभों को पिवट करना चाहते हैं, इसलिए आपको Controls में कई स्तंभों को अनपिवट करना होगा पहले टेबल, फिर पिवट। आपने इसे SQL Server 2008 के रूप में टैग किया है, ताकि आप CROSS APPLY का उपयोग कर सकें कॉलम को अनपिवट करने के लिए।

मैं निम्नलिखित कदम उठाने का सुझाव दूंगा। सबसे पहले, Controls को अनपिवट करें तालिका:

select 
  ProjectId,
  col = ControlCode +'_'+col,
  val
from
(
  select 
    c.ProjectId,
    c.ControlCode,
    c.ControlPoint,
    c.ControlScore,
    c.ControlValue
  from controls c
) d
cross apply
(
  select 'ControlPoint', cast(controlpoint as varchar(10)) union all
  select 'ControlScore', cast(ControlScore as varchar(10)) union all
  select 'ControlValue', ControlValue
) c (col, val)

देखें SQL Fiddle with Demo . यह आपकी कई पंक्तियों को इसी तरह के कई स्तंभों में बदलने वाला है:

| PROJECTID |            COL |     VAL |
|-----------|----------------|---------|
|      P001 | A_ControlPoint |   30.44 |
|      P001 | A_ControlScore |   65.00 |
|      P001 | A_ControlValue | Invalid |
|      P001 | C_ControlPoint |   45.30 |
|      P001 | C_ControlScore |   85.00 |
|      P001 | C_ControlValue |   Valid |

दूसरा, ControlChilds से डेटा प्राप्त करें एक समान प्रारूप में तालिका लेकिन अपने row_number() . का उपयोग करें प्रत्येक बच्चे के लिए एक क्रम निर्दिष्ट करने के लिए:

select 
  projectId,
  col = ControlCode+'_'+'Child'+cast(seq as varchar(10)),
  ControlChildValue
from
(
  select c.ProjectId,
    c.ControlCode,
    cc.ControlChildValue,
    row_number() over(partition by c.ProjectId, c.ControlCode
                      order by cc.ControlChildId) seq
  from controls c
  inner join controlchilds cc
    on c.controlid = cc.controlid
) d

देखें SQL Fiddle with Demo . यह इस तालिका से प्रारूप में डेटा प्राप्त करता है:

| PROJECTID |      COL | CONTROLCHILDVALUE |
|-----------|----------|-------------------|
|      P001 | A_Child1 |               Yes |
|      P001 | A_Child2 |                No |
|      P001 | A_Child3 |                NA |
|      P001 | A_Child4 |            Others |
|      P001 | C_Child1 |               Yes |
|      P001 | C_Child2 |         SomeValue |

अब, आप आसानी से UNION ALL का उपयोग कर सकते हैं दो प्रश्नों के बीच और PIVOT फ़ंक्शन लागू करें:

select ProjectId,
  A_ControlPoint, A_ControlScore, A_ControlValue,
  A_Child1, A_Child2, A_Child3, A_Child4,
  C_ControlPoint, C_ControlScore, C_ControlValue,
  C_Child1, C_Child2
from
(
  select 
    ProjectId,
    col = ControlCode +'_'+col,
    val
  from
  (
    select 
      c.ProjectId,
      c.ControlCode,
      c.ControlPoint,
      c.ControlScore,
      c.ControlValue
    from controls c
  ) d
  cross apply
  (
    select 'ControlPoint', cast(controlpoint as varchar(10)) union all
    select 'ControlScore', cast(ControlScore as varchar(10)) union all
    select 'ControlValue', ControlValue
  ) c (col, val)
  union all
  select 
    projectId,
    col = ControlCode+'_'+'Child'+cast(seq as varchar(10)),
    ControlChildValue
  from
  (
    select c.ProjectId,
      c.ControlCode,
      cc.ControlChildValue,
      row_number() over(partition by c.ProjectId, c.ControlCode
                        order by cc.ControlChildId) seq
    from controls c
    inner join controlchilds cc
      on c.controlid = cc.controlid
  ) d
) src
pivot
(
  max(val)
  for col in (A_ControlPoint, A_ControlScore, A_ControlValue,
              A_Child1, A_Child2, A_Child3, A_Child4,
              C_ControlPoint, C_ControlScore, C_ControlValue,
              C_Child1, C_Child2)
) piv;

देखें SQL Fiddle with Demo .

अब जब आपके पास सही तर्क है, तो आप इसे एक गतिशील SQL संस्करण में बदल सकते हैं:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(col) 
                    from 
                    (
                      select ControlCode,
                        col = ControlCode +'_'+col,
                        seq, 
                        so
                      from controls
                      cross apply
                      (
                        select 'ControlPoint', 0, 0 union all
                        select 'ControlScore', 0, 1 union all
                        select 'ControlValue', 0, 2 
                      ) c (col, seq, so)
                      union all
                      select  ControlCode,
                        col = ControlCode+'_'+'Child'+cast(seq as varchar(10)),
                        seq, 
                        3
                      from
                      (
                        select ControlCode, 
                          row_number() over(partition by c.ProjectId, c.ControlCode
                                                  order by cc.ControlChildId) seq
                        from controls c
                        inner join controlchilds cc
                          on c.controlid = cc.controlid
                      ) d
                    ) src
                    group by ControlCode, seq, col, so
                    order by ControlCode, so, seq
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT ProjectId, ' + @cols + ' 
            from 
            (
              select ProjectId,
                col = ControlCode +''_''+col,
                val
              from
              (
                select 
                  c.ProjectId,
                  c.ControlCode,
                  c.ControlPoint,
                  c.ControlScore,
                  c.ControlValue
                from controls c
              ) d
              cross apply
              (
                select ''ControlPoint'', cast(controlpoint as varchar(10)) union all
                select ''ControlScore'', cast(ControlScore as varchar(10)) union all
                select ''ControlValue'', ControlValue
              ) c (col, val)
              union all
              select 
                projectId,
                col = ControlCode+''_Child''+cast(seq as varchar(10)),
                ControlChildValue
              from
              (
                select c.ProjectId,
                  c.ControlCode,
                  cc.ControlChildValue,
                  row_number() over(partition by c.ProjectId, c.ControlCode
                                    order by cc.ControlChildId) seq
                from controls c
                inner join controlchilds cc
                  on c.controlid = cc.controlid
              ) d
            ) x
            pivot 
            (
                max(val)
                for col in (' + @cols + ')
            ) p '

exec sp_executesql @query;

देखें SQL Fiddle with Demo . मैंने कॉलम को उस क्रम में रखने के लिए गतिशील संस्करण लिखा था जिसका उपयोग आपने अपने नमूने में किया था। यह सॉर्ट ऑर्डर प्रकार के मान का उपयोग करके किया जा सकता है।

यह इसका अंतिम परिणाम देता है:

| PROJECTID | A_CONTROLPOINT | A_CONTROLSCORE | A_CONTROLVALUE | A_CHILD1 | A_CHILD2 | A_CHILD3 | A_CHILD4 | C_CONTROLPOINT | C_CONTROLSCORE | C_CONTROLVALUE | C_CHILD1 |  C_CHILD2 |
|-----------|----------------|----------------|----------------|----------|----------|----------|----------|----------------|----------------|----------------|----------|-----------|
|      P001 |          30.44 |          65.00 |        Invalid |      Yes |       No |       NA |   Others |          45.30 |          85.00 |          Valid |      Yes | SomeValue |


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर में समूहीकृत संयोजन

  2. सन्निहित अनुक्रमिक संख्याओं के समूहों की सीमाओं का पता कैसे लगाएं?

  3. SQL सर्वर क्वेरीज़ की शब्दावली — DBA के लिए एक स्टिक शिफ्ट

  4. SQL सर्वर में एकल क्वेरी में पाँचवाँ उच्चतम वेतन कैसे प्राप्त करें

  5. SQL सर्वर 2014:मूल बैकअप एन्क्रिप्शन