Có thể PIVOT trên một tuyên bố THÍCH


9

Có thể nhóm theo các yếu tố (như trong COLUMN LIKE='Value%') trong một PIVOTbảng không? Tôi có một bảng [DBT]. [Trạng thái] chứa các trạng thái khác nhau (của cơ sở dữ liệu, phiên bản, v.v.) và không muốn xoay vòng / truy vấn tất cả các giá trị SẢN PHẨM và TEST dưới dạng các giá trị đơn lẻ, nhưng nhóm chúng lại.

Ví dụ: Thay vì có các cột cho các trạng thái Prod, Prod ACC, Prod APP, .. vv Tôi sẽ chỉ có một cột chứa các giá trị cho Name LIKE 'Prod%'Name LIKE 'Test%'.

Những gì tôi có cho đến nay:

Bảng định nghĩa

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

Giá trị bảng

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')

Bảng trạng thái xoay vòng

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

Đầu ra cho đến nay

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 <>

Các dbfiddle cho đến nay.

Câu hỏi

Thay vì có nhiều hàng cho các giá trị Test...Prod....giá trị khác nhau , tôi muốn nhóm chúng lại, tương tự như sau:

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

Tôi không biết làm thế nào để giải quyết câu hỏi của mình. (Thành thật mà nói tôi chỉ mới nắm được PIVOT ngày hôm qua sau khi dùng thử và lỗi rộng rãi).

Câu hỏi này liên quan một cách lỏng lẻo đến câu hỏi Làm thế nào để tạo tổng / số lượng các mục được nhóm qua nhiều bảng tôi đã hỏi. Các bảng [DBT]. [Instance] và [DBT]. [Database] chứa một cột có [StatusID] tương ứng với bảng mà chúng ta đang xem bây giờ.

Câu trả lời:


11

SUM (TRƯỜNG HỢP

Đối với một số lượng tên hạn chế, bạn có thể sử dụng giải pháp SUM (CASE theo cách này:

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];

TRỤC

Nếu có một danh sách Tên đầy đủ nhưng chỉ một vài trong số chúng phải được viết lại, bạn có thể duy trì giải pháp PIVOT:

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;

db <> fiddle ở đây

NHIỀU NĂNG ĐỘNG

Nếu bạn cảm thấy hơi lười biếng và không muốn viết tất cả các tên cột, bạn có thể sử dụng truy vấn động:

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);

db <> fiddle ở đây


7

Tôi nghĩ điều quan trọng là phải phân tách chặt chẽ hai nhiệm vụ bạn đang cố gắng thực hiện trong một bước ở đây.

  1. Phân loại
  2. Biến đổi

Để phân loại dữ liệu, bản năng của tôi ở đây là đề xuất một bảng tra cứu để ánh xạ chặt chẽ các bản ghi vào một lớp cha. ví dụ

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) ;

... Trong đó bản ghi hạt giống trong StatusType( ID= 1 cho Status.StatusTypeIDmặc định) là bản ghi giữ chỗ có tên "Không xác định" hoặc tương tự.

Khi dữ liệu tra cứu được khởi tạo và các bản ghi cơ sở được cập nhật với các khóa chính xác, bạn có thể xoay vòng nội dung trái tim của bạn.

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;

Toàn bộ dbfiddle


Cảm ơn bạn cho giải pháp của bạn, nó là một giải pháp khá tốt. Tuy nhiên, tôi hiện không thể sửa đổi các định nghĩa bảng hiện có hoặc thêm vào thiết kế cơ sở dữ liệu.
John aka hot2use

1
Trước tiên, chọn dữ liệu vào một bảng tạm thời, theo cách đó bạn có quyền kiểm soát dữ liệu. Thả cám dỗ sau khi bạn chọn từ nó để hiển thị, nếu bạn muốn. Khi truy vấn của bạn được thực hiện, bạn có thể đưa nó vào một quy trình được lưu trữ, tự động quan tâm đến việc chọn vào cám dỗ và thả nó sau khi bạn hoàn thành.
khaoliang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.