2012-09-28 40 views
21

Tôi có một bảng của khách hàngđộng tạo ra các cột sql

Customer ID  Name   
    1    John   
    2    Lewis   
    3    Mary   

Tôi có một bảng CustomerRewards

TypeID   Description 
    1    Bronze 
    2    Silver 
    3    Gold 
    4    Platinum 
    5    AnotherOne 

Và final table

RewardID   TypeID   CustomerID 
    1    1     1 
    2    1     1 
    3    2     1 
    4    2     2 

Bảng customerTypes là năng động, nhiều các loại này có thể được thêm và xóa. Về cơ bản tất cả tôi muốn là các cột được tạo tự động và một số trong mỗi, một cái gì đó giống như

CustomerName  Bronze  Silver  Gold  Platinum  AnotherOne total 
    John    2    1   0   0    0   3 
    Lewis    0    1   0   0    0   1 
Grand TOTAL   2    2   0   0    0   4 

Vấn đề như tôi đã nói nó rằng loại năng động và khách hàng năng động vì vậy tôi cần các cột phải năng động tùy thuộc vào loại trong hệ thống

tôi đã gắn thẻ C# như tôi cần điều này trong một DataGridView

Cảm ơn trước

+2

Điều này trông giống như trục xoay. Tôi đã làm một vài, nhưng tôi không thể gõ một từ bộ nhớ. Có lẽ một cái nhìn trong DB tạo ra từ xoay vòng dữ liệu ở phía bên SQL? –

+1

Bạn có thể muốn trục động, nếu bạn cần làm điều này trong SQL. Xem, ví dụ: http://www.simple-talk.com/blogs/2007/09/14/pivots-with-dynamic-columns-in-sql-server-2005/ Nhưng đó không thực sự là giải pháp sạch. Nếu bạn có thể đợi để có được dữ liệu của bạn vào C#, bạn có thể sử dụng LINQ để làm điều này. –

+0

Chúng trông phức tạp! cảm ơn cho các ý kiến, tôi sẽ xem xét Pivot nhưng nếu có ai có một giải pháp dễ dàng xin vui lòng miễn phí – CR41G14

Trả lời

46

Bạn sẽ muốn sử dụng một hàm PIVOT cho việc này. Nếu bạn có một số cột đã biết, thì bạn có thể mã hóa cứng các giá trị:

select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne] 
from 
(
    select c.name, 
    cr.description, 
    r.typeid 
    from customers c 
    left join rewards r 
    on c.id = r.customerid 
    left join customerrewards cr 
    on r.typeid = cr.typeid 
) x 
pivot 
(
    count(typeid) 
    for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne]) 
) p; 

Xem SQL Fiddle with Demo.

Bây giờ nếu bạn có một số không rõ các cột, sau đó bạn có thể sử dụng SQL động để PIVOT:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(description) 
        from customerrewards 
        group by description, typeid 
        order by typeid 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT name,' + @cols + ' from 
      (
       select c.name, 
        cr.description, 
        r.typeid 
       from customers c 
       left join rewards r 
        on c.id = r.customerid 
       left join customerrewards cr 
        on r.typeid = cr.typeid 
      ) x 
      pivot 
      (
       count(typeid) 
       for description in (' + @cols + ') 
      ) p ' 

execute(@query) 

Xem SQL Fiddle With Demo

Nếu bạn cần bao gồm cột Total, sau đó bạn có thể sử dụng ROLLUP (Static Version Demo):

select name, sum([Bronze]) Bronze, sum([Silver]) Silver, 
    sum([Gold]) Gold, sum([Platinum]) Platinum, sum([AnotherOne]) AnotherOne 
from 
(
    select name, [Bronze], [Silver], [Gold], [Platinum], [AnotherOne] 
    from 
    (
    select c.name, 
     cr.description, 
     r.typeid 
    from customers c 
    left join rewards r 
     on c.id = r.customerid 
    left join customerrewards cr 
     on r.typeid = cr.typeid 
) x 
    pivot 
    (
    count(typeid) 
    for description in ([Bronze], [Silver], [Gold], [Platinum], [AnotherOne]) 
) p 
) x 
group by name with rollup 

Phiên bản động (Demo):

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

select @cols = STUFF((SELECT ',' + QUOTENAME(description) 
        from customerrewards 
        group by description, typeid 
        order by typeid 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

select @colsRollup 
     = STUFF((SELECT ', Sum(' + QUOTENAME(description) + ') as '+ QUOTENAME(description) 
        from customerrewards 
        group by description, typeid 
        order by typeid 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 


set @query 
      = 'SELECT name, '+ @colsRollup + ' 
      FROM 
      (
       SELECT name,' + @cols + ' from 
       (
        select c.name, 
         cr.description, 
         r.typeid 
        from customers c 
        left join rewards r 
         on c.id = r.customerid 
        left join customerrewards cr 
         on r.typeid = cr.typeid 
       ) x 
       pivot 
       (
        count(typeid) 
        for description in (' + @cols + ') 
       ) p 
      ) x1 
       GROUP BY name with ROLLUP' 

execute(@query) 
+0

Câu trả lời xuất sắc! – CR41G14

+1

Bạn có một lỗi SQL Injection lỗ hổng/khả năng sử dụng: = STUFF ((SELECT ', Sum (' + QUOTENAME (mô tả) + ') là' + mô tả Nên: = STUFF ((SELECT ', Sum (' + QUOTENAME (mô tả) + ') là' + QUOTENAME (mô tả) Nếu không, đó là một bài đăng tuyệt vời! – shellster

+0

@shellster Yup, bạn nói đúng. Tôi đã cập nhật mã của mình. – Taryn

Các vấn đề liên quan