क्या एक LIKE स्टेटमेंट पर PIVOT करना संभव है


9

क्या COLUMN LIKE='Value%'किसी PIVOTतालिका में तत्वों (जैसे ) द्वारा समूह बनाना संभव है ? मेरे पास एक टेबल है [डीबीटी]। [स्टेटस] जिसमें विभिन्न स्टेटस (डेटाबेस, इंस्टेंस आदि) होते हैं और सभी PROD और TEST मानों को सिंगल वैल्यू के रूप में पिवट / क्वेरी नहीं करना चाहते हैं, लेकिन उन्हें ग्रुप करें।

उदाहरण के बजाय स्थितियों के लिए कॉलम होने के Prod, Prod ACC, Prod APP, .. आदि मैं केवल एक के लिए मूल्यों वाले कॉलम होता है Name LIKE 'Prod%'और Name LIKE 'Test%'

मेरे पास अब तक क्या है:

तालिका परिभाषा

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

तालिका मान

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

Pivoted स्थिति तालिका

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

आउटपुट तो बहुत दूर

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

डाटाबेस <> बेला

Dbfiddle अब तक।

सवाल

विभिन्न Test... और Prod....मानों के लिए कई पंक्तियों के बजाय , मैं उन्हें निम्न के समान समूहबद्ध करना पसंद करूंगा:

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

मेरे पास कोई सवाल नहीं है कि मैं अपने प्रश्न को हल करने के बारे में कैसे जाऊं। (ईमानदार होने के लिए मैंने केवल व्यापक परीक्षण और त्रुटियों के बाद कल PIVOT को पकड़ लिया)।

यह सवाल इस सवाल से संबंधित है कि मैंने पहले से ही पूछी गई कई तालिकाओं पर समूहीकृत वस्तुओं की रकम / गिनती कैसे बनाई । तालिकाओं [DBT]। [उदाहरण] और [DBT]। [डेटाबेस] [StatusID] के साथ एक कॉलम होता है जो उस तालिका से मेल खाता है जिसे हम अभी देख रहे हैं।

जवाबों:


11

योग (मामला

नामों की एक सीमित संख्या के लिए आप इस तरह एक SUM (CASE समाधान का उपयोग कर सकते हैं:

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

धुरी

यदि नामों की एक विस्तृत सूची है, लेकिन उनमें से कुछ को ही फिर से लिखा जाना चाहिए, तो आप 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

डायनामिक QUERY

यदि आप थोड़ा आलसी महसूस करते हैं और सभी स्तंभ नामों को लिखना नहीं चाहते हैं, तो आप एक गतिशील क्वेरी का उपयोग कर सकते हैं:

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


7

मुझे लगता है कि जिन दो कार्यों को आप यहां एक चरण में करने की कोशिश कर रहे हैं, उन्हें कड़ाई से अलग करना महत्वपूर्ण है।

  1. वर्गीकरण
  2. परिवर्तन

डेटा को वर्गीकृत करने के लिए, मेरी वृत्ति यहाँ मूल कक्षा के रिकॉर्ड को सख्ती से मैप करने के लिए लुकअप टेबल की सिफारिश करना है। जैसे

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

... जहाँ बीज रिकॉर्ड StatusType( ID= 1 Status.StatusTypeIDडिफ़ॉल्ट के लिए) एक प्लेसहोल्डर रिकॉर्ड "अज्ञात" या इसी तरह का है।

जब लुकअप डेटा सीड किया जाता है और बेस रिकॉर्ड को सही कुंजियों के साथ अपडेट किया जाता है, तो आप अपने दिल की सामग्री को पिवट कर सकते हैं।

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;

पूर्ण dbfiddle


आपके समाधान के लिए धन्यवाद, यह एक बहुत अच्छा समाधान है। हालाँकि, मैं वर्तमान में मौजूदा टेबल परिभाषाओं को संशोधित करने या डेटाबेस डिज़ाइन में जोड़ने में असमर्थ हूँ।
जॉन उर्फ ​​हॉट 2use

1
पहले एक अस्थायी तालिका में डेटा का चयन करें, जिस तरह से आपके पास डेटा पर नियंत्रण है। यदि आप चाहते हैं तो प्रदर्शन के लिए आपके द्वारा चुने जाने के बाद, उसे छोड़ दें। एक बार आपकी क्वेरी हो जाने के बाद, आप इसे एक संग्रहीत प्रक्रिया में सेंध लगा सकते हैं जो आपके द्वारा किए जाने के बाद स्वचालित रूप से प्रलोभन में चयन करने और इसे छोड़ने का ध्यान रखता है।
खलियांग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.