LIKE ifadesinde PIVOT yapmak mümkün mü


9

Tablodaki öğelere (olduğu gibi COLUMN LIKE='Value%') göre gruplamak mümkün müdür PIVOT? Ben bir tablo [DBT] var. [Durum] çeşitli durumlar (veritabanları, örnekler, vb.) İçerir ve pivot / sorgu tüm PROD ve TEST değerlerini tek değerler olarak, ancak gruplandırmak istemiyorum.

Örneğin Yerine durumları için sütunlar sahip Prod, Prod ACC, Prod APP, .. vb ben ilişkin değerleri içeren tek bir sütun olurdu Name LIKE 'Prod%'ve Name LIKE 'Test%'.

Şimdiye kadar ne var:

Tablo Tanımı

CREATE TABLE [DBT].[Status](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Status] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY],
 CONSTRAINT [IX_Status] UNIQUE NONCLUSTERED 
(
    [Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]

GO

Tablo Değerleri

INSERT INTO [DBT].[Status]
(
    -- ID -- this column value is auto-generated
    Name
)
VALUES
('Test ACC'),
('Test APP'),
('Test DBA'),
('Prod ACC'),
('Prod APP'),
('Prod DBA'),
('Prod'),
('Test'),
('Migrated'),
('Offline'),
('Reserved')

Pivotlanmış Durum Tablosu

SELECT 'Database Status' AS [DB Status], 
[1] AS [Test ACC], [2] AS [Test APP], [3] AS [Test DBA], [4] AS [Prod ACC], [5] AS [Prod APP], [6] AS [Prod DBA], [7] AS [Prod], [8] AS [Test], [9] AS [Migrated], [10] AS [Offline], [11] AS [Reserved] 
FROM 
(
    SELECT ID, Name  FROM [DBT].[Status]
) AS Source
PIVOT
(
    COUNT(Name) FOR ID IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11])
) AS PivotTable

Çıktı

DB Status       Test ACC    Test APP    Test DBA    Prod ACC    Prod APP    Prod DBA    Prod        Test        Migrated    Offline     Reserved
--------------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
Database Status 1           1           1           1           1           1           1           1           1           1           1

db <> keman

Dbfiddle şimdiye kadar.

Soru

Çeşitli Test... ve Prod....değerler için birden çok satıra sahip olmak yerine, bunları aşağıdakilere benzer şekilde gruplandırmayı tercih ederim:

DB Status       | Test | Prod | Migrated | Offline | Reserved   
--------------- | ---- | ---- | -------- | ------- | --------
Database Status |    4 |    4 |        1 |       1 |        1

Sorumu nasıl çözeceğime dair hiçbir fikrim yok. (Dürüst olmak gerekirse, sadece kapsamlı deneme ve hatalardan sonra dün PIVOT'u yakaladım).

Bu soru, zaten sorduğum birden çok tablo üzerinde gruplanmış öğelerin toplamları / sayıları nasıl oluşturulur sorusuyla ilgili . [DBT]. [Örnek] ve [DBT]. [Veritabanı] tabloları, [StatusID] ile şu anda baktığımız tabloya karşılık gelen bir sütun içeriyor.

Yanıtlar:


11

SUM (DURUM

Sınırlı sayıda Ad için bir SUM (CASE çözümü) bu şekilde kullanabilirsiniz:

SELECT 
    'Database status' as [DB Status],
    SUM(CASE WHEN Name LIKE 'Test%' THEN 1 ELSE 0 END) As Test,
    SUM(CASE WHEN Name LIKE 'Prod%' THEN 1 ELSE 0 END) AS Prod,
    SUM(CASE WHEN Name = 'Migrated' THEN 1 ELSE 0 END) AS Migrated,
    SUM(CASE WHEN Name = 'Offline' THEN 1 ELSE 0 END) AS Offline,
    SUM(CASE WHEN Name = 'Reserved' THEN 1 ELSE 0 END) AS Reserved
FROM 
    [Status];

EKSEN

Kapsamlı bir Ad listesi varsa, ancak bunların sadece birkaçının yeniden yazılması gerekiyorsa, PIVOT çözümünü koruyabilirsiniz:

SELECT 'Database Status' AS [DB Status],
[Test], [Prod], [Migrated], [Offline], [Reserved]
FROM
(
    SELECT 
        ID, 
        CASE
            WHEN Name LIKE 'Test%' THEN 'Test'
            WHEN Name LIKE 'Prod%' THEN 'Prod'
            ELSE Name
        END AS Name
    FROM 
        [Status]
) AS Source
PIVOT
(
    COUNT(ID) FOR Name IN ([Test], [Prod], [Migrated], [Offline], [Reserved])
) AS PivotTable;

burada keman

DİNAMİK SORGULAMA

Biraz tembel hissediyorsanız ve tüm sütun adlarını yazmak istemiyorsanız dinamik bir sorgu kullanabilirsiniz:

DECLARE @cols nvarchar(max);

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(CASE WHEN Name LIKE 'Test%' THEN 'Test'
                                                    WHEN Name LIKE 'Prod%' THEN 'Prod'
                                                    ELSE Name END)
                   FROM [Status]
                   FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');

DECLARE @cmd nvarchar(max);

SET @cmd = 
'SELECT ''Database Status'' AS [DB Status],' + @cols + ' FROM
    (SELECT 
        ID, 
        CASE
            WHEN Name LIKE ''Test%'' THEN ''Test''
            WHEN Name LIKE ''Prod%'' THEN ''Prod''
            ELSE Name
        END AS Name
    FROM 
        [Status]
) AS Source
PIVOT
(
    COUNT(ID) FOR Name IN (' + @cols + ')
) PVT'

EXEC(@cmd);

burada keman


7

Bence burada gerçekleştirmeye çalıştığınız iki görevi bir adımda kesin olarak ayırmanız önemlidir.

  1. sınıflandırma
  2. dönüşüm

Verileri sınıflandırmak için burada içgüdüm, kayıtları bir üst sınıfa titizlikle eşlemek için bir arama tablosu önermektir. Örneğin

CREATE TABLE StatusType (
  ID     INT         IDENTITY PRIMARY KEY,
  [Name] VARCHAR(10) NOT NULL UNIQUE
);
GO
ALTER TABLE [Status] 
  ADD StatusTypeID INT NOT NULL 
    DEFAULT 1
    FOREIGN KEY REFERENCES StatusType (ID) ;

... burada tohum kaydı StatusType( varsayılan değer IDiçin = 1 Status.StatusTypeID) "Bilinmeyen" veya benzeri bir yer tutucu kayıttır.

Arama verileri tohumlandığında ve temel kayıtlar doğru tuşlarla güncellendiğinde, kalbinizin içeriğine dönebilirsiniz.

select 'Database Status' AS [DB Status],
    [Test], [Prod], [Migrated], [Offline], [Reserved]
from (
    select s.ID,
           st.Name as StatusTypeName
    from status s
    join statusType st on st.ID = s.StatusTypeID
) as Source
pivot (
    count(ID) for StatusTypeName in ([Test],[Prod],[Migrated],[Offline],[Reserved],[Unknown])
) as pvt;

Tam dbfiddle


Çözümünüz için teşekkür ederim, oldukça iyi bir çözüm. Ancak, şu anda varolan tablo tanımlarını değiştiremiyorum veya veritabanı tasarımına ekleyemiyorum.
John aka hot2use

1
Önce verileri geçici bir tabloya seçin, böylece veriler üzerinde kontrol sahibi olursunuz. İsterseniz, ekrandan seçim yaptıktan sonra cazibeyi bırakın. Sorgunuz tamamlandıktan sonra, otomatik olarak cazip hale getirmeyi seçtikten ve bitirdikten sonra bırakarak saklanan bir yordam haline getirebilirsiniz.
khaoliang
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.