2013-03-30 5 views
20

मुझे नीचे दिए गए परिणाम बनाने में सहायता चाहिए। मैंने एक एसक्यूएल पिवट के बारे में सोचा लेकिन मुझे नहीं पता कि इसका उपयोग कैसे किया जाए। कुछ उदाहरणों को देखा और समाधान के साथ नहीं आ सकते हैं। इसे पूरा करने के तरीके पर कोई अन्य विचार भी स्वागत है। स्थिति कॉलम गतिशील रूप से जेनरेट किया जाना चाहिए।मुझे यह जानने की जरूरत है कि क्रॉसस्टैब क्वेरी कैसे बनाएं

, तीन टेबल, संपत्ति, assettypes है assetstatus

 
Table: assets 
assetid  int 
assettag varchar(25) 
assettype int 
assetstatus int 

Table: assettypes 
id   int 
typename varchar(20) (ex: Desktop, Laptop, Server, etc.) 

Table: assetstatus 
id   int 
statusname varchar(20) (ex: Deployed, Inventory, Shipped, etc.) 

वांछित परिणाम:

 
AssetType  Total Deployed Inventory Shipped  ... 
----------------------------------------------------------- 
Desktop   100  75  20   5  ... 
Laptop   75  56  19   1  ... 
Server   60  50  10   0  ... 
कुछ डाटा

:

 
assets table: 
1,hol1234,1,1 
2,hol1233,1,2 
3,hol3421,2,3 
4,svr1234,3,1 

assettypes table: 
1,Desktop 
2,Laptop 
3,Server 

assetstatus table: 
1,Deployed 
2,Inventory 
3,Shipped 
+0

क्या RDBMS प्रयोग कर रहे हैं? – Taryn

+0

(75, 56, 50) तैनात मूल्य कहां से आते हैं? वे आपके डेटा में प्रकट नहीं होते हैं। –

+0

इस समय पर मुझे बहुत समझ नहीं आती है क्या आपके पास कुछ तालिकाओं में कुछ उदाहरण हैं, कुछ वास्तविक पंक्तियां ... संदर्भ के बिंदु के रूप में तालिकाओं के बीच कुछ समानता होनी चाहिए उन्हें एक साथ लिंक करें ... यदि आप वह विवरण प्रदान करते हैं तो मुझे इसमें जाना होगा। –

उत्तर

40

परिवर्तन के इस प्रकार के एक धुरी कहा जाता है। आपने यह निर्दिष्ट नहीं किया है कि आप किस डेटाबेस का उपयोग कर रहे हैं, इसलिए मैं SQL सर्वर और MySQL के लिए उत्तर प्रदान करूंगा।


एसक्यूएल सर्वर: आप एसक्यूएल सर्वर 2005+ आप PIVOT समारोह लागू कर सकते हैं प्रयोग कर रहे हैं।

यदि आपके पास ज्ञात संख्या है जो आप कॉलम में कनवर्ट करना चाहते हैं तो आप क्वेरी को हार्ड-कोड कर सकते हैं।

select typename, total, Deployed, Inventory, shipped 
from 
(
    select count(*) over(partition by t.typename) total, 
    s.statusname, 
    t.typename 
    from assets a 
    inner join assettypes t 
    on a.assettype = t.id 
    inner join assetstatus s 
    on a.assetstatus = s.id 
) d 
pivot 
(
    count(statusname) 
    for statusname in (Deployed, Inventory, shipped) 
) piv; 

SQL Fiddle with Demo देखें।

लेकिन अगर आप status मूल्यों की संख्या ज्ञात नहीं है, तो आप गतिशील एसक्यूएल उपयोग करने के लिए रन-टाइम में स्तंभों की सूची उत्पन्न करने के लिए की आवश्यकता होगी।

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

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

set @query = 'SELECT typename, total,' + @cols + ' from 
      (
       select count(*) over(partition by t.typename) total, 
        s.statusname, 
        t.typename 
       from assets a 
       inner join assettypes t 
        on a.assettype = t.id 
       inner join assetstatus s 
        on a.assetstatus = s.id 
      ) x 
      pivot 
      (
       count(statusname) 
       for statusname in (' + @cols + ') 
      ) p ' 

execute(@query) 

देखें SQL Fiddle with Demo

यह भी एक मामला अभिव्यक्ति के साथ एक समग्र समारोह का उपयोग कर लिखा जा सकता है:

select typename, 
    total, 
    sum(case when statusname ='Deployed' then 1 else 0 end) Deployed, 
    sum(case when statusname ='Inventory' then 1 else 0 end) Inventory, 
    sum(case when statusname ='Shipped' then 1 else 0 end) Shipped 
from 
(
    select count(*) over(partition by t.typename) total, 
    s.statusname, 
    t.typename 
    from assets a 
    inner join assettypes t 
    on a.assettype = t.id 
    inner join assetstatus s 
    on a.assetstatus = s.id 
) d 
group by typename, total 

देखें SQL Fiddle with Demo


MySQL: इस डेटाबेस करना es पिवट फ़ंक्शन नहीं है इसलिए आपको कुल फ़ंक्शन और CASE अभिव्यक्ति का उपयोग करना होगा। यह भी कार्यों विंडोइंग नहीं है, तो आप निम्न के थोड़ा क्वेरी में परिवर्तन करना होगा:

select typename, 
    total, 
    sum(case when statusname ='Deployed' then 1 else 0 end) Deployed, 
    sum(case when statusname ='Inventory' then 1 else 0 end) Inventory, 
    sum(case when statusname ='Shipped' then 1 else 0 end) Shipped 
from 
(
    select t.typename, 
    (select count(*) 
    from assets a1 
    where a1.assettype = t.id 
    group by a1.assettype) total, 
    s.statusname 
    from assets a 
    inner join assettypes t 
    on a.assettype = t.id 
    inner join assetstatus s 
    on a.assetstatus = s.id 
) d 
group by typename, total; 

SQL Fiddle with Demo

देखें तो अगर आप MySQL में एक गतिशील समाधान की जरूरत है, तो आप एक का उपयोग करना होगा तैयार बयान उत्पन्न करने के लिए निष्पादित करने के लिए एसक्यूएल स्ट्रिंग:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'sum(CASE WHEN statusname = ''', 
     statusname, 
     ''' THEN 1 else 0 END) AS `', 
     statusname, '`' 
    ) 
) INTO @sql 
FROM assetstatus; 

SET @sql 
    = CONCAT('SELECT typename, 
       total, ', @sql, ' 
      from 
      (
       select t.typename, 
       (select count(*) 
       from assets a1 
       where a1.assettype = t.id 
       group by a1.assettype) total, 
       s.statusname 
       from assets a 
       inner join assettypes t 
       on a.assettype = t.id 
       inner join assetstatus s 
       on a.assetstatus = s.id 
      ) d 
      group by typename, total'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

SQL Fiddle with Demo देखें।

परिणाम दोनों डेटाबेस में सभी प्रश्नों के लिए एक ही है:

| TYPENAME | TOTAL | DEPLOYED | INVENTORY | SHIPPED | 
----------------------------------------------------- 
| Desktop |  2 |  1 |   1 |  0 | 
| Laptop |  1 |  0 |   0 |  1 | 
| Server |  1 |  1 |   0 |  0 | 
+0

एक ज्ञात संख्या वाला SQL सर्वर खूबसूरती से काम करता है। एक अज्ञात संख्या गतिशील एसक्यूएल के साथ मुझे कुछ त्रुटियां मिलती हैं: संदेश 1038, स्तर 15, राज्य 4, रेखा 15 कोई ऑब्जेक्ट या कॉलम नाम गुम या खाली है। विवरणों में चयन के लिए, प्रत्येक कॉलम का नाम सत्यापित करें। अन्य बयानों के लिए, खाली उपनाम नामों की तलाश करें। "" या [] के रूप में परिभाषित एलियंस की अनुमति नहीं है। उपनाम को वैध नाम में बदलें। – Sam

+1

@ सैम क्या आप [SQL Fiddle] (http://www.sqlfiddle.com/#!3/d7915/7) को उस कोड के साथ संपादित कर सकते हैं, जिसे आप चलाने की कोशिश कर रहे हैं? कोड को दाएं पैनल में रखें और फिर एसक्यूएल निष्पादित करें। फिर यहां एक टिप्पणी में लिंक पोस्ट करें। – Taryn

+0

मैं टेबल बनाता हूं, कोड निष्पादित करता हूं और सभी ठीक काम करता है। जब मैं इसे अपने डीबी पर लागू करता हूं तो मुझे एक त्रुटि मिलती है। फील्ड नाम सही हैं। पता नहीं क्यों यह काम नहीं कर रहा है। – Sam

संबंधित मुद्दे