मैं MySQL में पिवट टेबल आउटपुट कैसे वापस कर सकता हूं?


311

अगर मेरे पास एक MySQL टेबल कुछ इस तरह है:

company_name कार्रवाई पेजकाउंट
-------------------------------
कंपनी एक प्रिंट 3
कंपनी एक प्रिंट 2
कंपनी एक प्रिंट 3
कंपनी B EMAIL   
कंपनी बी प्रिंट 2
कंपनी बी प्रिंट 2
कंपनी बी प्रिंट 1
कंपनी एक प्रिंट 3

क्या इस तरह से आउटपुट पाने के लिए MySQL क्वेरी चलाना संभव है:

company_name EMAIL PRINT 1 पृष्ठ PRINT 2 पृष्ठ PRINT 3 पृष्ठ
-------------------------------------------------- -----------
कंपनीए 0 0 1 3
कंपनीबी 1 1 2 0

विचार यह है कि pagecountआउटपुट कॉलम राशि अलग-अलग हो सकती है इसलिए, प्रत्येक action/ pagecountजोड़ी के लिए एक कॉलम और फिर प्रति हिट की संख्या को प्रतिबिंबित करना चाहिए company_name। मुझे यकीन नहीं है कि अगर इसे एक धुरी तालिका कहा जाता है, लेकिन किसी ने सुझाव दिया है कि?


3
इसे Pivoting कहा जाता है और SQL के बाहर यह परिवर्तन करने के लिए बहुत, बहुत तेज है।
एनबी

1
एक्सेल इस तरह से चीजों से गुजरता है, यह MySQL में वास्तव में मुश्किल है क्योंकि कोई "क्रोस्टैब" ऑपरेटर नहीं है :(
डेव रिक्स

हाँ यह वर्तमान में एक्सेल में हाथ से किया गया है और हम इसे स्वचालित करने की कोशिश कर रहे हैं।
पीकू

3
यहाँ मुझे स्टेप बाय स्टेप उदाहरण मिला: पिवट टेबल को कैसे ऑटोमेट करना है । और यह
Devid G

1
@giannischristofakis - यह वास्तव में आप और आपके सहकर्मियों को सरल बनाने पर निर्भर करता है। जब से मैंने टिप्पणी (4 वर्ष) पोस्ट की है, तब से प्रौद्योगिकी बहुत अच्छी तरह से पकड़ी गई है, इसलिए यह पूरी तरह से आप जो महसूस करते हैं वह बेहतर है - यह एप्लिकेशन या एसक्यूएल में हो। उदाहरण के लिए, मेरे काम पर हम समान समस्या से निपटते हैं, लेकिन हम SQL और इन-ऐप दृष्टिकोण दोनों को मिला रहे हैं। मूल रूप से, मैं आपकी राय का जवाब देने के अलावा आपकी कोई मदद नहीं कर सकता और यह आपकी जरूरत नहीं है :)
NB

जवाबों:


235

यह मूल रूप से एक धुरी तालिका है।

इसे प्राप्त करने के बारे में एक अच्छा ट्यूटोरियल यहां पाया जा सकता है: http://www.artfulsoftware.com/infotree/qrytip.php?id=78

मैं इस पोस्ट को पढ़ने की सलाह देता हूं और अपनी आवश्यकताओं के लिए इस समाधान को अनुकूलित करता हूं।

अपडेट करें

ऊपर दिए गए लिंक के बाद वर्तमान में उपलब्ध नहीं है, मुझे लगता है कि आप सभी के लिए कुछ अतिरिक्त जानकारी प्रदान करने के लिए बाध्य महसूस कर रहे हैं यहाँ mysql धुरी जवाब के लिए खोज। इसमें वास्तव में बहुत अधिक जानकारी थी, और मैं वहां से सब कुछ नहीं डालूंगा (इससे भी अधिक जब मैं सिर्फ उनके विशाल ज्ञान को कॉपी नहीं करना चाहता), लेकिन मैं धुरी से निपटने के बारे में कुछ सलाह दूंगा पेकू से उदाहरण के साथ आमतौर पर वर्ग रास्ता सारणी जो पहले स्थान पर सवाल पूछा था।

हो सकता है कि लिंक जल्द ही वापस आ जाए, मैं इसके लिए नजर रखूंगा।

स्प्रेडशीट तरीका ...

बहुत से लोग सिर्फ इस उद्देश्य के लिए MSExcel, OpenOffice या अन्य स्प्रेडशीट-टूल जैसे टूल का उपयोग करते हैं। यह एक वैध समाधान है, बस वहाँ पर डेटा की प्रतिलिपि बनाएँ और इसे हल करने के लिए GUI ऑफ़र टूल का उपयोग करें।

लेकिन ... यह सवाल नहीं था, और यह कुछ नुकसान भी पहुंचा सकता है, जैसे कि डेटा को स्प्रेडशीट, समस्याग्रस्त स्केलिंग और इतने पर कैसे प्राप्त किया जाए।

एसक्यूएल तरीका ...

उनकी तालिका कुछ इस तरह दी गई है:

CREATE TABLE `test_pivot` (
  `pid` bigint(20) NOT NULL AUTO_INCREMENT,
  `company_name` varchar(32) DEFAULT NULL,
  `action` varchar(16) DEFAULT NULL,
  `pagecount` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`pid`)
) ENGINE=MyISAM;

अब उसकी / उसकी वांछित तालिका देखें:

company_name    EMAIL   PRINT 1 pages   PRINT 2 pages   PRINT 3 pages
-------------------------------------------------------------
CompanyA        0       0               1               3
CompanyB        1       1               2               0

पंक्तियाँ ( EMAIL, PRINT x pages) स्थितियों से मिलती जुलती हैं। मुख्य समूह द्वारा है company_name

इस स्थिति को सेट करने के लिए CASE-statement का उपयोग करने के लिए चिल्लाता है । कुछ से समूह के लिए, अच्छी तरह से, उपयोग ... GROUP BY

इस धुरी को प्रदान करने वाला मूल SQL कुछ इस तरह दिख सकता है:

SELECT  P.`company_name`,
    COUNT(
        CASE 
            WHEN P.`action`='EMAIL' 
            THEN 1 
            ELSE NULL 
        END
    ) AS 'EMAIL',
    COUNT(
        CASE 
            WHEN P.`action`='PRINT' AND P.`pagecount` = '1' 
            THEN P.`pagecount` 
            ELSE NULL 
        END
    ) AS 'PRINT 1 pages',
    COUNT(
        CASE 
            WHEN P.`action`='PRINT' AND P.`pagecount` = '2' 
            THEN P.`pagecount` 
            ELSE NULL 
        END
    ) AS 'PRINT 2 pages',
    COUNT(
        CASE 
            WHEN P.`action`='PRINT' AND P.`pagecount` = '3' 
            THEN P.`pagecount` 
            ELSE NULL 
        END
    ) AS 'PRINT 3 pages'
FROM    test_pivot P
GROUP BY P.`company_name`;

यह वांछित परिणाम बहुत तेजी से प्रदान करना चाहिए। इस दृष्टिकोण के लिए प्रमुख नकारात्मक पक्ष, अपनी धुरी तालिका में जितनी अधिक पंक्तियाँ आप चाहते हैं, उतनी ही अधिक शर्तें आपको अपने SQL कथन में परिभाषित करने की आवश्यकता है।

इससे निपटा जा सकता है, इसलिए भी, लोग तैयार किए गए बयानों, दिनचर्या, काउंटर और इस तरह का उपयोग करते हैं।

इस विषय के बारे में कुछ अतिरिक्त लिंक:


4
लिंक अब के लिए काम करने लगता है ... अगर यह फिर कभी नीचे जाता है, तो इन पर प्रयास करें: Google का कैश webcache.googleusercontent.com/… या इंटरनेट वेबैक मशीन ( web.archive.org/web/20070303120558 * * artfulsoftware.com/) इंफोट्री / क्वेरीज़। एफपी )
लाइकेनजेस

लिंक इस url पर उपलब्ध है artfulsoftware.com/infotree/qrytip.php?id=78
MrPandav

1
"अगर", "केस", या "GROUP_CONCAT" का उपयोग किए बिना एक पिवट टेबल उत्पन्न करने का एक और तरीका है: en.wikibooks.org/wiki/MySQL/Pivot_table
user25131499

आप अपने CASE से ELSE NULL को हटा सकते हैं क्योंकि टोपी डिफ़ॉल्ट व्यवहार है (और सशर्त एकत्रीकरण पर्याप्त पर्याप्त है)
कैयस जार्ड

86

मेरा समाधान टी-एसक्यूएल में बिना किसी पिवोट्स के है:

SELECT
    CompanyName,  
    SUM(CASE WHEN (action='EMAIL') THEN 1 ELSE 0 END) AS Email,
    SUM(CASE WHEN (action='PRINT' AND pagecount=1) THEN 1 ELSE 0 END) AS Print1Pages,
    SUM(CASE WHEN (action='PRINT' AND pagecount=2) THEN 1 ELSE 0 END) AS Print2Pages,
    SUM(CASE WHEN (action='PRINT' AND pagecount=3) THEN 1 ELSE 0 END) AS Print3Pages
FROM 
    Company
GROUP BY 
    CompanyName

2
यह PostgreSQL पर भी मेरे लिए काम करता है। मैं इस विधि को पोस्टग्रेज पर
क्रोस्टैब

2
"मेरा समाधान बिना किसी पिवोट्स के टी-एसक्यूएल में है:" न केवल एसक्यूएल सर्वर यह सबसे डेटाबेस विक्रेताओं पर काम करना चाहिए जो एएनएसआई मानकों का पालन करता है। ध्यान दें कि SUM()केवल संख्यात्मक डेटा के साथ काम कर सकते हैं यदि आप स्ट्रिंग को पिंग करने के लिए उपयोग करते हैं, तो आपको उपयोग करना होगाMAX()
रेमंड निजलैंड

1
मुझे लगता है कि मामले में आकस्मिक है SUM(CASE WHEN (action='PRINT' AND pagecount=1) THEN 1 ELSE 0 END), आप बस SUM(action='PRINT' AND pagecount=1)तब कर सकते हैं जब स्थिति 1सच में बदल जाएगी और 0जब झूठी होगी
काजाक्स

1
@kajacx हां, हालांकि यह डेटाबेस पर आवश्यक है कि बूलियन हेरफेर की तरह नहीं है। "एक लंबे समय तक वाक्य रचना जो सभी dB पर काम करती है" और "केवल उस पर काम करने वाले छोटे वाक्यविन्यास" के बीच एक विकल्प को देखते हुए ... "मैं पूर्व
कायुस जार्ड

66

MySQL के लिए आप सीधे SUM()फ़ंक्शन में स्थितियां डाल सकते हैं और इसका मूल्यांकन बूलियन के रूप में किया01 जाएगा या इस प्रकार आप IF/CASEबयानों का उपयोग किए बिना अपने मानदंड के आधार पर अपनी गणना कर सकते हैं

SELECT
    company_name,  
    SUM(action = 'EMAIL')AS Email,
    SUM(action = 'PRINT' AND pagecount = 1)AS Print1Pages,
    SUM(action = 'PRINT' AND pagecount = 2)AS Print2Pages,
    SUM(action = 'PRINT' AND pagecount = 3)AS Print3Pages
FROM t
GROUP BY company_name

DEMO


1
यह वास्तव में साफ है। क्या आप जानते हैं कि क्या यह अन्य प्लेटफार्मों (जैसे पोस्टग्रेज) पर मानकों का अनुपालन है?
उत्तोलन

3
@itsols केवल इसके लिए नहीं है - मेरा खालिक विशिष्ट
एम खालिद जुनैद

@itsols: मैंने एक और मानक SQL संस्करण जोड़ा है । पोस्टग्रेज में एक समर्पित crosstab()कार्य
इरविन ब्रान्डेसटेटर

2
SQLite
SBF

37

गतिशील धुरी के लिए, के GROUP_CONCATसाथ उपयोग करें CONCATGroup_concat समारोह विभिन्न विकल्पों के साथ एक स्ट्रिंग में एक समूह से तार संयोजित करता।

SET @sql = NULL;
SELECT
    GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(CASE WHEN action = "',
      action,'"  AND ', 
           (CASE WHEN pagecount IS NOT NULL 
           THEN CONCAT("pagecount = ",pagecount) 
           ELSE pagecount IS NULL END),
      ' THEN 1 ELSE 0 end) AS ',
      action, IFNULL(pagecount,'')

    )
  )
INTO @sql
FROM
  t;

SET @sql = CONCAT('SELECT company_name, ', @sql, ' 
                  FROM t 
                   GROUP BY company_name');

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

यहाँ डेमो


2
पेसियर, सच्चा आदमी लेकिन गतिशील दृष्टिकोण के लिए अपने सबसे अच्छे दृष्टिकोण में से एक के लिए
अभिषेक गुप्ता

2
यह अच्छी तरह से काम करता है यदि आपके पास "कार्रवाई" कॉलम में कई मान हैं या उस सूची को समय के साथ बढ़ने की उम्मीद है, क्योंकि प्रत्येक मूल्य के लिए एक केस स्टेटमेंट लिखना समय लेने और अद्यतित रहने के लिए कठिन हो सकता है।
पैट्रिक मर्फी

23

बुलियन लॉजिक का उपयोग करते हुए एक स्टारडार्ड-एसक्यूएल संस्करण :

SELECT company_name
     , COUNT(action = 'EMAIL' OR NULL) AS "Email"
     , COUNT(action = 'PRINT' AND pagecount = 1 OR NULL) AS "Print 1 pages"
     , COUNT(action = 'PRINT' AND pagecount = 2 OR NULL) AS "Print 2 pages"
     , COUNT(action = 'PRINT' AND pagecount = 3 OR NULL) AS "Print 3 pages"
FROM   tbl
GROUP  BY company_name;

एसक्यूएल फिडल।

कैसे?

TRUE OR NULL पैदावार TRUE
FALSE OR NULLपैदावार NULL
NULL OR NULLपैदावार NULL
और COUNTकेवल गैर-शून्य मान गिनाता है। देखा।


@ इरविन, लेकिन आप कैसे जानेंगे कि तीन कॉलम हैं? अगर 5 है तो क्या होगा? 10? 20?
पचेरियर

@ स्पेसर: प्रश्न में उदाहरण यह सुझाव देता है। किसी भी तरह से, SQL रिटर्न प्रकार जानने की मांग करता है। एक पूरी तरह से गतिशील क्वेरी संभव नहीं है। यदि आउटपुट कॉलम की संख्या अलग-अलग हो सकती है, तो आपको दो चरणों की आवश्यकता होगी: 1 क्वेरी बनाएं, 2: इसे निष्पादित करें।
इरविन ब्रान्डसेट्टर 10

11

सही उत्तर है:

select table_record_id,
group_concat(if(value_name='note', value_text, NULL)) as note
,group_concat(if(value_name='hire_date', value_text, NULL)) as hire_date
,group_concat(if(value_name='termination_date', value_text, NULL)) as termination_date
,group_concat(if(value_name='department', value_text, NULL)) as department
,group_concat(if(value_name='reporting_to', value_text, NULL)) as reporting_to
,group_concat(if(value_name='shift_start_time', value_text, NULL)) as shift_start_time
,group_concat(if(value_name='shift_end_time', value_text, NULL)) as shift_end_time
from other_value
where table_name = 'employee'
and is_active = 'y'
and is_deleted = 'n'
GROUP BY table_record_id

1
क्या यह सिर्फ एक उदाहरण है जो आपके हाथ में था? other_valueतालिका की संरचना क्या है ?
पैट्रिक मर्फी

1
"सही उत्तर है:" सबसे अधिक संभावना नहीं है क्योंकि यह SETअवशिष्ट मान को बढ़ाने के लिए क्वेरी को याद नहीं कर रहा है जो कि 1024 के लिए GROUP_CONCAT के लिए 1024 तक सीमित है। 1024 के बाद Group_CONCAT केवल स्ट्रिंग को त्रुटि के बिना काट देता है जिसका अर्थ अप्रत्याशित परिणाम हो सकता है ..
रेमंड निजलैंड

क्षमा करें दोस्तों आगे के विवरण याद नहीं रख सकते। मैं मज़े के लिए सामान करता हूं और फिर पूरी परियोजना को भूल जाता हूं या नष्ट कर देता हूं। लेकिन जब मैं एक चुनौती पर ठोकर खाता हूं तो मैं साझा करता हूं कि मैंने इसे कैसे तय किया। मुझे पता है कि मेरा उदाहरण बहुत विस्तृत नहीं है, लेकिन मुझे लगता है कि यह उन लोगों को दिशा दे सकता है जो जानते हैं कि वे क्या खिलाफ हैं :)
तल्हा

9

MySQL Pivot तालिका जनरेटर नामक एक उपकरण है, यह आपको वेब आधारित धुरी तालिका बनाने में मदद कर सकता है जिसे आप बाद में एक्सेल करने के लिए निर्यात कर सकते हैं (यदि आपको पसंद है)। यह तब काम कर सकता है जब आपका डेटा किसी एक तालिका में या कई तालिकाओं में हो।

आपको केवल स्तंभों के डेटा स्रोत को निर्दिष्ट करना है (यह डायनेमिक कॉलम का समर्थन करता है), पंक्तियों, तालिका और तालिका संबंध के शरीर में मान (यदि कोई हो) MySQL धुरी तालिका

इस टूल का मुख पृष्ठ http://mysqlpivottable.net है


3
select t3.name, sum(t3.prod_A) as Prod_A, sum(t3.prod_B) as Prod_B, sum(t3.prod_C) as    Prod_C, sum(t3.prod_D) as Prod_D, sum(t3.prod_E) as Prod_E  
from
(select t2.name as name, 
case when t2.prodid = 1 then t2.counts
else 0 end  prod_A, 

case when t2.prodid = 2 then t2.counts
else 0 end prod_B,

case when t2.prodid = 3 then t2.counts
else 0 end prod_C,

case when t2.prodid = 4 then t2.counts
else 0 end prod_D, 

case when t2.prodid = "5" then t2.counts
else 0 end prod_E

from 
(SELECT partners.name as name, sales.products_id as prodid, count(products.name) as counts
FROM test.sales left outer join test.partners on sales.partners_id = partners.id
left outer join test.products on sales.products_id = products.id 
where sales.partners_id = partners.id and sales.products_id = products.id group by partners.name, prodid) t2) t3

group by t3.name ;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.