MySQL - कई वर्षों में संबंधों के साथ विभिन्न महीनों में अधिकतम राशि


9

इस सवाल से प्रेरित था यह एक [बंद कर दिया] और लगभग इस के समान है एक लेकिन अलग RDBMS का उपयोग (PostgreSQL बनाम MySQL)।

मान लीजिए कि मेरे पास ट्यूमर की सूची है (यह डेटा वास्तविक डेटा से सिम्युलेटेड है):

CREATE table illness (nature_of_illness VARCHAR(25), created_at DATETIME);

INSERT INTO illness VALUES ('Cervix', '2018-01-03 15:45:40');
INSERT INTO illness VALUES ('Cervix', '2018-01-03 15:45:40');
INSERT INTO illness VALUES ('Cervix', '2018-01-03 15:45:40');
INSERT INTO illness VALUES ('Cervix', '2018-01-03 15:45:40');
INSERT INTO illness VALUES ('Cervix', '2018-01-03 15:45:40');
INSERT INTO illness VALUES ('Lung',   '2018-01-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2018-02-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2018-02-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2018-02-03 17:50:32');
INSERT INTO illness VALUES ('Cervix', '2018-02-03 17:50:32');
-- 2017, with 1 Cervix and Lung each for the month of Jan - tie!
INSERT INTO illness VALUES ('Cervix', '2017-01-03 15:45:40');
INSERT INTO illness VALUES ('Lung',   '2017-01-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2017-02-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2017-02-03 17:50:32');
INSERT INTO illness VALUES ('Lung',   '2017-02-03 17:50:32');
INSERT INTO illness VALUES ('Cervix', '2017-02-03 17:50:32');

आप यह पता लगाना चाहते हैं कि दिए गए महीने में कौन सा विशेष ट्यूमर सबसे आम था - अब तक बहुत अच्छा!

अब, आप देखेंगे कि 2017 के 1 महीने के लिए, एक टाई है - तो यह कोई मतलब नहीं है कि जो कोई भी बेतरतीब ढंग से एक लेने के लिए और जवाब के रूप में दे - ताकि संबंधों को शामिल किया जाए - यह समस्या को और अधिक चुनौतीपूर्ण बनाता है।

सही जवाब है:

  Year    Month  Tumour count      Type
  2017        1             1    Cervix  -- note tie
  2017        1             1      Lung  --   "   "
  2017        2             3      Lung
  2018        1             5    Cervix
  2018        2             3      Lung

महीने के नाम को पूर्णांक के बजाय पाठ के रूप में प्रकट करने के लिए एक और बोनस होगा।

मेरे पास एक समाधान है, लेकिन यह काफी जटिल है - मैं जानना चाहता हूं कि मेरा समाधान इष्टतम है या नहीं। MySQL फिडेल यहाँ है !


मैं समझता हूं कि यह एक एसक्यूएल विशिष्ट प्रश्न है, लेकिन टाइम सीरीज़ डेटाबेस का उपयोग करके इसे बहुत सरल बनाया जा सकता है।
सैश करें

2
@ सैश, यह ज्यादातर SQL DBMS के साथ बहुत सरल किया जा सकता है, जिसमें MySQL / MariaDB के नए संस्करण शामिल हैं। MySQL 5.6 SQL92 के बाद आविष्कार की गई अधिक कार्यक्षमता को लागू नहीं करता है।
लेनार्ट

जवाबों:


4

इसे हल करने का मेरा प्रयास इस प्रकार है। मैं किसी भी सलाह की सराहना करूँगा कि इस क्वेरी को कैसे बेहतर बनाया जा सकता है:

SELECT 
  t3.c_year AS "Year",
  t3.c_month AS "Month", 
  t3.il_mc AS  "Tumour count", 
  t4.ill_nat AS "Type" FROM
(
  SELECT c_year, c_month, il_mc FROM
  (
    SELECT  
    c_year, 
    c_month,
    MAX(month_count) AS il_mc
  FROM
    (
      SELECT nature_of_illness as illness,
        EXTRACT(YEAR  FROM created_at) AS c_year,
        EXTRACT(MONTH FROM created_at) AS c_month,
        COUNT(EXTRACT(MONTH FROM created_at)) AS month_count
      FROM illness
      GROUP BY illness, c_year, c_month
      ORDER BY c_year, c_month
    ) AS t1
  GROUP BY c_year, c_month
  ) AS t2
) AS t3
JOIN
(
SELECT 
  EXTRACT(YEAR FROM created_at) AS t_year, 
  EXTRACT(MONTH FROM created_at) AS t_month,  
  nature_of_illness AS ill_nat, 
  COUNT(nature_of_illness) AS ill_cnt
FROM illness
GROUP BY t_year, t_month, nature_of_illness
ORDER BY t_year, t_month, nature_of_illness
) AS t4
ON t3.c_year = t4.t_year
AND t3.c_month = t4.t_month
AND t3.il_mc = t4.ill_cnt

और यह सही परिणाम देता है, जैसा कि यहां की बेला में देखा जा सकता है !


मुझे नहीं लगता कि यह बहुत सरल करना संभव है। एक विकल्प जो दिमाग में आता है, वह है कि वर्ष और तिथि के लिए अधिकतम गणना के बराबर गिनती प्राप्त करने के लिए एक सम्मिलित होने के बजाय एक उप-चयन। संभव है, लेकिन शायद ही सरल। एक अन्य विकल्प वैरिएबल का उपयोग करके विभाजन (... पर विभाजन) की नक़ल करना है और उम्मीद है कि जब तक क्वेरी को बदलना होगा, तब तक आपको एक नई नौकरी मिल जाएगी ;-)
लेनार्ट

उम्मीद है कि कुछ भी होने से पहले हम MySQL 8 पर होंगे :-)। यह अंततः 21 वीं सदी में MySQL लाता है! Analytics, CTE का, उचित REGEXPs - अच्छा दिखता है - भले ही आप INTERSECTs और कुछ अन्य पकड़ नहीं कर सकते, लेकिन ऐसा लगता है कि Oracle ने वास्तव में इस रिलीज़ में बहुत कुछ डाल दिया है।
वेयर्स

0

MySQL-8.0 और CTE का उपयोग करते हुए हम पहली बार tmpवर्ष / माह / द्वारा समुच्चय गणना समूह के रूप में बनाते हैं nature_of_illness, RANK()समान मानों को समान मान प्रदान करते हैं cताकि डुप्लिकेट अधिकतम का हिसाब लगाया जाए:

 SELECT y as 'Year',mon as 'Month',c as 'Tumor Count', nature_of_illness as 'Type'
 FROM (
   WITH tmp AS ( 
    SELECT YEAR(created_at) as y, MONTH(created_at) as mon, COUNT(*) as c, nature_of_illness
    FROM illness
    GROUP BY y, mon, nature_of_illness
   )
   SELECT y, mon, c, nature_of_illness,
   RANK() OVER (PARTITION BY y, mon ORDER BY c DESC) as `rank`
   FROM tmp
 ) AS tmp2 
WHERE `rank` = 1
ORDER BY y, mon
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.