यहां आपके प्रश्न 1 का समाधान दिया गया है जो बहुत तेजी से चलेगा, क्योंकि आपके पास कई पूर्ण तालिका स्कैन और आश्रित उपश्रेणियां हैं। यहां आपके पास केवल एक टेबल स्कैन होगा (और शायद एक अस्थायी तालिका, यह निर्भर करता है कि आपका डेटा कितना बड़ा है और आपको कितनी मेमोरी मिली है)। मुझे लगता है कि आप इसे यहां अपने प्रश्न में आसानी से समायोजित कर सकते हैं। प्रश्न 2 (मैंने इसे वास्तव में नहीं पढ़ा है) शायद इसका उत्तर भी दिया गया है क्योंकि अब केवल where date_column = whatever
जोड़ना आसान है।
select * from (
select
t.*,
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
@prev_sn := SerialNumber,
@prev_toner := Remain_Toner_Black
from
Table1 t
, (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber limit 1) var_init
order by SerialNumber, id
) sq
where select_it = 1
- इसे sqlfiddle में लाइव काम करते हुए देखें
संपादित करें:
व्याख्या:
इस लाइन के साथ
, (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber
हम सिर्फ वेरिएबल्स को इनिशियलाइज़ करते हैं @prev_toner
और @prev_sn
उड़ान पर। यह वैसा ही है जैसे क्वेरी में यह लाइन बिल्कुल नहीं है लेकिन क्वेरी के सामने लिखना है
SET @prev_toner = 0;
SET @prev_sn = (select serialnumber from your_table order by serialnumber limit 1);
SELECT ...
तो, @prev_sn को मान निर्दिष्ट करने के लिए क्वेरी क्यों करें और क्रमांक द्वारा ऑर्डर क्यों करें? द्वारा आदेश बहुत महत्वपूर्ण है। आदेश के बिना कोई गारंटीकृत आदेश नहीं है जिसमें पंक्तियां वापस आती हैं। साथ ही हम पिछली पंक्तियों के मान को वेरिएबल के साथ एक्सेस करेंगे, इसलिए यह महत्वपूर्ण है कि समान सीरियल नंबर "एक साथ समूहीकृत" हों।
सेलेक्ट क्लॉज में कॉलम का मूल्यांकन एक के बाद एक किया जाता है, इसलिए यह महत्वपूर्ण है कि आप पहले इस लाइन को चुनें
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
इन दो पंक्तियों को चुनने से पहले
@prev_sn := SerialNumber,
@prev_toner := Remain_Toner_Black
ऐसा क्यों है? अंतिम दो पंक्तियाँ वर्तमान पंक्तियों के मानों को चरों को निर्दिष्ट करती हैं। इसलिए इस पंक्ति में
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
चर अभी भी पिछली पंक्तियों के मान रखते हैं। और हम यहां जो करते हैं वह यह कहने के अलावा और कुछ नहीं है "यदि कॉलम Remain_Toner_Black में पिछली पंक्तियों का मान वर्तमान पंक्ति और में एक से छोटा है पिछली पंक्तियों की क्रम संख्या वास्तविक पंक्तियों की क्रम संख्या के समान है, 1 लौटाएं, अन्यथा 0 लौटाएं।"
तब हम केवल बाहरी क्वेरी में कह सकते हैं "हर पंक्ति का चयन करें, जहां ऊपर 1 लौटाया गया है"।
आपकी क्वेरी को देखते हुए, आपको इन सभी उपश्रेणियों की आवश्यकता नहीं है। वे बहुत महंगे और अनावश्यक हैं। वास्तव में यह काफी पागल है। प्रश्न के इस भाग में
SELECT a.ID,
a.Time,
a.SerialNumber,
a.Remain_Toner_Black,
a.Remain_Toner_Cyan,
a.Remain_Toner_Magenta,
a.Remain_Toner_Yellow,
(
SELECT COUNT(*)
FROM Reports c
WHERE c.SerialNumber = a.SerialNumber AND
c.ID <= a.ID) AS RowNumber
FROM Reports a
आप संपूर्ण तालिका . का चयन करें और हर पंक्ति के लिए आप उस समूह के भीतर पंक्तियों की गणना करते हैं। यह एक आश्रित सबक्वायरी है। सभी के पास किसी न किसी प्रकार की पंक्ति संख्या होनी चाहिए। फिर आप इसे दूसरी बार करते हैं, ताकि आप पिछली पंक्ति प्राप्त करने के लिए उन दो अस्थायी तालिकाओं में शामिल हो सकें। वास्तव में, कोई आश्चर्य नहीं कि प्रदर्शन भयानक है।
तो, अपनी क्वेरी के लिए मेरे समाधान को कैसे समायोजित करें? एक चर के बजाय मैं Remain_Toner_Black के लिए पिछली पंक्ति प्राप्त करता था, काले, सियान, मैजेंटा और पीले रंग के लिए चार का उपयोग करता था। और बस प्रिंटर और ग्राहक तालिका में शामिल हों जैसे आपने पहले ही किया था। द्वारा आदेश को न भूलें और आपका काम हो गया।