2013-03-28 22 views
14

Dinamik bir pivot sql ifadesinin nasıl yazılacağını belirlemeye çalışın. TEST_NAME'un 12 farklı değere sahip olması (12 sütuna sahip olması). VAL’nın bir kısmı Int, Decimal veya Varchar veri türleri olacaktır. Gördüğüm örneklerin birçoğu, dahil toplamı içeriyor. Düz bir değer pivotu arıyorum.Toplama olmadan sütunlara satırları döndürme

Source Table 

╔═══════════╦══════╦═══════╗ 
║ TEST_NAME ║ SBNO ║ VAL ║ 
╠═══════════╬══════╬═══════╣ 
║ Test1  ║ 1 ║ 0.304 ║ 
║ Test1  ║ 2 ║ 0.31 ║ 
║ Test1  ║ 3 ║ 0.306 ║ 
║ Test2  ║ 1 ║ 2.3 ║ 
║ Test2  ║ 2 ║ 2.5 ║ 
║ Test2  ║ 3 ║ 2.4 ║ 
║ Test3  ║ 1 ║ PASS ║ 
║ Test3  ║ 2 ║ PASS ║ 
╚═══════════╩══════╩═══════╝ 


Desired Output 
╔══════════════════════════╗ 
║ SBNO Test1 Test2 Test3 ║ 
╠══════════════════════════╣ 
║ 1 0.304 2.3 PASS ║ 
║ 2 0.31 2.5 PASS ║ 
║ 3 0.306 2.4 NULL ║ 
╚══════════════════════════╝ 

cevap

22

PIVOT işlevi işe almak için bir toplama gerektirir. VAL sütununuzun varchar olduğu anlaşılıyor, dolayısıyla MAX veya MIN toplama işlevlerini kullanmanız gerekecek.

test sayısı sınırlıdır, o zaman sabit şekilde kod değerleri:

select sbno, Test1, Test2, Test3 
from 
(
    select test_name, sbno, val 
    from yourtable 
) d 
pivot 
(
    max(val) 
    for test_name in (Test1, Test2, Test3) 
) piv; 

SQL Fiddle with Demo bakınız.

OP'nizde, sütunlara dönüşecek daha fazla sayıda satırınız olacağını belirttiniz.

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(TEST_NAME) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT sbno,' + @cols + ' 
      from 
      (
       select test_name, sbno, val 
       from yourtable 
      ) x 
      pivot 
      (
       max(val) 
       for test_name in (' + @cols + ') 
      ) p ' 

execute(@query) 

SQL Fiddle with Demo bakınız: Eğer durum buysa, o zaman dinamik SQL kullanabilirsiniz.

| SBNO | TEST1 | TEST2 | TEST3 | 
--------------------------------- 
| 1 | 0.304 | 2.3 | PASS | 
| 2 | 0.31 | 2.5 | PASS | 
| 3 | 0.306 | 2.4 | (null) | 
+0

Harika bir yanıt, C# ile aynı yaklaşımı kullanmak mümkün mü? – Oliver

+0

@Oliver C# içinde dönme yolları var ama bunlara aşina değilim. SO üzerindeki linq-to-sql ile ilgili bazı sorulara pivot ile bakmanızı öneririm. Bir pivot aramada bulunabilecek birkaç tane var. – Taryn

4

Toplama olmadan PIVOT'un herhangi bir yolu yoktur.

CREATE TABLE #table1 
(
    TEST_NAME VARCHAR(10), 
    SBNO VARCHAR(10), 
    VAL VARCHAR(10) 
); 

INSERT INTO #table1 (TEST_NAME, SBNO, VAL) 
VALUES ('Test1' ,'1', '0.304'), 
     ('Test1' ,'2', '0.31'), 
     ('Test1' ,'3', '0.306'), 
     ('Test2' ,'1', '2.3'), 
     ('Test2' ,'2', '2.5'), 
     ('Test2' ,'3', '2.4'), 
     ('Test3' ,'1', 'PASS'), 
     ('Test3' ,'2', 'PASS') 

WITH T AS 
(
    SELECT SBNO, VAL, TEST_NAME  
     FROM #table1 
) 
SELECT * 
    FROM T 
PIVOT (MAX(VAL) FOR TEST_NAME IN([Test1], [Test2], [Test3])) P 
0

bir geçici çözüm zorunlu toplama daima yalnızca bir kayda uygulanmasını sağlamak için olabilir:

iki sürümü aynı sonucu verecektir. Excel'de örneğin çıkış olabilir:

SO15674373 example

nerede Satır Etiketleri altındaki benzersiz bir dizin numaraları ile hücrelerin bir sütun içeriyor.