MySQL की धुरी पंक्ति को स्तंभों की गतिशील संख्या में


81

आइए बताते हैं कि मेरे पास तीन अलग-अलग MySQL टेबल हैं:

तालिका products:

id | name
 1   Product A
 2   Product B

तालिका partners:

id | name
 1   Partner A
 2   Partner B

तालिका sales:

partners_id | products_id
          1             2
          2             5
          1             5
          1             3
          1             4
          1             5
          2             2
          2             4
          2             3
          1             1

मैं स्तंभों के रूप में पंक्तियों और उत्पादों में भागीदारों के साथ एक तालिका प्राप्त करना चाहूंगा। अब तक मैं इस तरह एक आउटपुट प्राप्त करने में सक्षम था:

name      | name      | COUNT( * )
Partner A   Product A          1
Partner A   Product B          1
Partner A   Product C          1
Partner A   Product D          1
Partner A   Product E          2
Partner B   Product B          1
Partner B   Product C          1
Partner B   Product D          1
Partner B   Product E          1

इस क्वेरी का उपयोग करना:

SELECT partners.name, products.name, COUNT( * ) 
FROM sales
JOIN products ON sales.products_id = products.id
JOIN partners ON sales.partners_id = partners.id
GROUP BY sales.partners_id, sales.products_id
LIMIT 0 , 30

लेकिन मैं इसके बजाय कुछ करना चाहेंगे:

partner_name | Product A | Product B | Product C | Product D | Product E
Partner A              1           1           1           1           2
Partner B              0           1           1           1           1

समस्या यह है कि मैं यह नहीं बता सकता कि उत्पादों की तालिका में पंक्तियों के आधार पर मेरे पास कितने उत्पाद हैं ताकि कॉलम संख्या को गतिशील रूप से बदलने की आवश्यकता हो।

यह बहुत अच्छा जवाब mysql: T-SQL Pivot के साथ काम नहीं करता है ? पंक्ति मानों से तालिका कॉलम बनाने की संभावना


कई सुझावों के लिए कॉलम से लिंक रो का संदर्भ लें ।
भाविन पोकिया


@BhavinPokiya एक MS SQL-Server लिंक है जो आपने प्रदान किया है, जबकि इसे MySQL के रूप में टैग किया गया है।
मैटसोम

जवाबों:


107

दुर्भाग्य से MySQL में एक PIVOTफ़ंक्शन नहीं है जो मूल रूप से आप क्या करने की कोशिश कर रहे हैं। तो आपको एक CASEकथन के साथ एक समुच्चय फ़ंक्शन का उपयोग करना होगा :

select pt.partner_name,
  count(case when pd.product_name = 'Product A' THEN 1 END) ProductA,
  count(case when pd.product_name = 'Product B' THEN 1 END) ProductB,
  count(case when pd.product_name = 'Product C' THEN 1 END) ProductC,
  count(case when pd.product_name = 'Product D' THEN 1 END) ProductD,
  count(case when pd.product_name = 'Product E' THEN 1 END) ProductE
from partners pt
left join sales s
  on pt.part_id = s.partner_id
left join products pd
  on s.product_id = pd.prod_id
group by pt.partner_name

SQL डेमो देखें

चूंकि आप उन उत्पादों को नहीं जानते हैं जिन्हें आप शायद इस गतिशील रूप से करना चाहते हैं। यह तैयार किए गए बयानों का उपयोग करके किया जा सकता है।

डायनामिक पिवट टेबल (पंक्तियों को कॉलम में बदलना) से आपका कोड इस तरह दिखेगा:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'count(case when Product_Name = ''',
      Product_Name,
      ''' then 1 end) AS ',
      replace(Product_Name, ' ', '')
    )
  ) INTO @sql
from products;

SET @sql = CONCAT('SELECT pt.partner_name, ', @sql, ' from partners pt
left join sales s
  on pt.part_id = s.partner_id
left join products pd
  on s.product_id = pd.prod_id
group by pt.partner_name');

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

SQL डेमो देखें

यह शायद ध्यान देने योग्य है कि GROUP_CONCATडिफ़ॉल्ट रूप से 1024 बाइट्स तक सीमित है। आप इसे अपनी प्रक्रिया की अवधि के लिए उच्चतर सेट करके इसके चारों ओर काम कर सकते हैं, अर्थात।SET @@group_concat_max_len = 32000;


2
"Max_len" के बारे में अंत में टिप्पणी एक जीवनरक्षक थी! पारितोषिक के लिए धन्यवाद।
एडवर्ड

1
यदि आप अधिक गतिशील धुरी प्रश्नों की तलाश कर रहे हैं, तो कृपया इसे देखें: boynux.com/creating-pivot-reports-in-mysql
Boynux

यदि उत्पाद का नाम है तो क्या होता हैProductA') from partners pt; truncate partners;
avatarofhope2

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