2012-03-01 11 views
10

तक जोड़ सकें, मैं निम्न तालिका में केवल कुछ पंक्तियों का चयन कैसे कर सकता हूं ताकि वे कुछ मूल्य तक पहुंच सकें?एसक्यूएल किसी तालिका में कुछ पंक्तियों का चयन करें ताकि वे कुछ मान

Table 
----- 
id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
1 | 0.0 | 0.0 | 10 | 20 
2 | 1.5 | 0.0 | 7.5 | 18 
3 | 1.0 | 2.0 | 7.5 | 18 
4 | 0.0 | 0.5 | 5 | 13 

चलो कहते हैं कि, शीर्ष मूल्य मैं चाहता हूँ 57 है चलो ...

तो मैं पिछली तालिका की पंक्तियां चुनें करने की जरूरत है ऐसा है कि qty1 + qty2 + qty3 + प्रत्येक पंक्ति के qty4, जब तक मिलता है वह 57 मूल्य, और अन्य पंक्तियों को त्यागें। इस उदाहरण में, मैं मिलेगा निम्नलिखित:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
1 | 0.0 | 0.0 | 10 | 20 
2 | 1.5 | 0.0 | 7.5 | 18 

10 क्योंकि + 20 + 1,5 + 7,5 + 18 = 57, इसलिए मैं पंक्तियों 3 & 4 त्यागने ...

अब मैं शीर्ष कि इच्छा मूल्य, 50 है तो मैं मिलना चाहिए:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
1 | 0.0 | 0.0 | 10 | 20 
2 | 1.5 | 0.0 | 7.5 | 11 

के बाद से इन मूल्यों से 50 योग, और पंक्ति 2 से 7, qty4 बाहर छोड़ दिया है ... (btw पंक्तियों को है, क्योंकि इस खास तरह से आदेश दिया जाता है जिस क्रम में मैं qtys की रकम के लिए खाता बनाना चाहता हूं ... यह पहले आर को समेटने के लिए मान्य नहीं है ओउ 1, फिर 3, फिर 2 फिर 4, उदाहरण के लिए ... उन्हें हमेशा 1,2,3,4 क्रम में समझा जाना चाहिए ...)

यदि मुझे इसका पूरक चाहिए तो क्या होगा? मेरा मतलब है, दूसरी दो पंक्तियों को मुझे अंतिम परिणाम में नहीं मिला था।

पहला मामला:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
3 | 1.0 | 2.0 | 7.5 | 18 
4 | 0.0 | 0.5 | 5 | 13 

दूसरा मामला:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
2 | 0.0 | 0.0 | 0.0 | 7 
3 | 1.0 | 2.0 | 7.5 | 18 
4 | 0.0 | 0.5 | 5 | 13 

(दूसरे मामले भी जटिल है, कैसे के बारे में प्राप्त करने के है:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
1 | 0.0 | 0.0 | 10 | 20 

मूल qtys को जोड़कर क्योंकि पंक्ति 2 की 50 मान से अधिक हो जाएगी, मैंने इसे छोड़ दिया ... इस मामले में पूरक बस होना चाहिए:

id | qty1 | qty2 | qty3 | qty4 
------------------------------ 
2 | 1.5 | 0.0 | 7.5 | 18 
3 | 1.0 | 2.0 | 7.5 | 18 
4 | 0.0 | 0.5 | 5 | 13 

)

+1

मैं जटिल प्रश्न के बहुत लिखा है, और मैं एक चुनौती पर ले जा पसंद है, लेकिन यह उन दुर्लभ मामलों केवल आपके प्रक्रियात्मक कोड लिखने के लिए भीख माँगता है कि में से एक है आपकी पसंद की भाषा में। सरलीकृत दूसरे मामले के लिए भी –

+0

? पोस्ट के अंत में आखिरी वाले कोष्ठक में ...? –

+1

सरलीकृत दूसरा मामला एक क्वेरी के रूप में करने योग्य है। यदि आप केवल अपने प्रश्न को संशोधित करने के लिए संशोधित करते हैं (या केवल एक नया प्रश्न बनाएं जो केवल इसके लिए पूछता है), तो मैं मदद कर सकता हूं। –

उत्तर

7

चलो इसे इस तरह से रखें: यदि एसक्यूएल एक धर्म था तो मैं इस समाधान को प्रदान करने के लिए नरक में जाऊंगा। एसक्यूएल इस तरह की समस्याओं को हल करने के लिए नहीं है, इसलिए कोई भी समाधान भयानक होगा।मेरा कोई अपवाद नहीं :)

set @limitValue := 50; 
select id, newQty1, newQty2, newQty3, newQty4 from (
    select id, 
    if(@limitValue - qty1 > 0, qty1, greatest(@limitValue, 0)) newQty1, 
    @limitValue := @limitValue - qty1 Total1, 
    if(@limitValue - qty2 > 0, qty2, greatest(@limitValue, 0)) newQty2, 
    @limitValue := @limitValue - qty2 Total2, 
    if(@limitValue - qty3 > 0, qty3, greatest(@limitValue, 0)) newQty3, 
    @limitValue := @limitValue - qty3 Total3, 
    if(@limitValue - qty4 > 0, qty4, greatest(@limitValue, 0)) newQty4, 
    @limitValue := @limitValue - qty4 Total4 
    from (
    select id, qty1, qty2, qty3, qty4, 
     @rowTotal < @limitValue Useful, 
     @previousRowTotal := @rowTotal PreviousRowTotal, 
     @rowTotal := @rowTotal + qty1 + qty2 + qty3 + qty4 AllRowsTotal, 
     @rowTotal - @previousRowTotal CurrentRowTotal 
    from t, 
    (select @rowTotal := 0, @previousRowTotal := 0) S1 
) MarkedUseful 
    where useful = 1 
) Final 

उपलब्ध कराए गए आंकड़ों के लिए है इस में जो परिणाम:

set @limitValue := 50; 
select t1.id, 
    coalesce(t1.qty1 - newQty1, t1.qty1) newQty1, 
    coalesce(t1.qty2 - newQty2, t1.qty2) newQty2, 
    coalesce(t1.qty3 - newQty3, t1.qty3) newQty3, 
    coalesce(t1.qty4 - newQty4, t1.qty4) newQty4 
from t t1 left join (
    select id, 
    if(@limitValue - qty1 > 0, qty1, greatest(@limitValue, 0)) newQty1, 
    @limitValue := @limitValue - qty1 Total1, 
    if(@limitValue - qty2 > 0, qty2, greatest(@limitValue, 0)) newQty2, 
    @limitValue := @limitValue - qty2 Total2, 
    if(@limitValue - qty3 > 0, qty3, greatest(@limitValue, 0)) newQty3, 
    @limitValue := @limitValue - qty3 Total3, 
    if(@limitValue - qty4 > 0, qty4, greatest(@limitValue, 0)) newQty4, 
    @limitValue := @limitValue - qty4 Total4 
    from (
     select id, qty1, qty2, qty3, qty4, 
     @rowTotal < @limitValue Useful, 
     @previousRowTotal := @rowTotal PreviousRowTotal, 
     @rowTotal := @rowTotal + qty1 + qty2 + qty3 + qty4 AllRowsTotal, 
     @rowTotal - @previousRowTotal CurrentRowTotal 
     from t, 
     (select @rowTotal := 0, @previousRowTotal := 0) S1 
    ) MarkedUseful 
    where useful = 1 
) Final 
on t1.id = final.id 
where Total1 < 0 or Total2 < 0 or Total3 < 0 or Total4 < 0 or final.id is null 

उपलब्ध कराए गए आंकड़ों के लिए यह परिणाम:

+----+---------+---------+---------+---------+ 
| ID | NEWQTY1 | NEWQTY2 | NEWQTY3 | NEWQTY4 | 
+----+---------+---------+---------+---------+ 
| 1 | 0  |  0 | 10  |  20 | 
| 2 | 1.5  |  0 | 7.5  |  11 | 
+----+---------+---------+---------+---------+ 

और पूरक

+----+---------+---------+---------+---------+ 
| ID | NEWQTY1 | NEWQTY2 | NEWQTY3 | NEWQTY4 | 
+----+---------+---------+---------+---------+ 
| 2 |  0 | 0  | 0  |  7 | 
| 3 |  1 | 2  | 7.5  |  18 | 
| 4 |  0 | 0.5  | 5  |  13 | 
+----+---------+---------+---------+---------+ 

आनंद लें!

+0

ने अभी उपलब्ध समाधानों का प्रयास किया, लेकिन पूरक मामले के लिए, उसी नमूने का उपयोग करके डेटा, मुझे आपके द्वारा दिखाया गया परिणाम नहीं मिला, लेकिन डेटा तालिका से केवल मूल 4 पंक्तियां ... –

+0

अब यह काम करता है! मुझे नहीं पता कि मैंने पिछली बार गलत क्या किया है :) मुझे इसका परीक्षण करने दें और इसे अपने असली मामले में लागू करें और मैं आपको बक्षीस के बारे में उत्तर दूंगा;) –

+0

निश्चित रूप से, अपना समय लें :) –

13

कोष्ठक में सरल विकल्प बहुत बुरा नहीं है:

SELECT foo1.* 
    FROM foo AS foo1 
    JOIN foo AS foo2 
    ON foo2.id <= foo1.id 
GROUP 
    BY foo1.id 
HAVING SUM(foo2.qty1 + foo2.qty2 + foo2.qty3 + foo2.qty4) <= 57 
; 

(आप तालिका के नाम का उल्लेख नहीं था, इसलिए मैं foo साथ चला गया)।

पूरक होगा:

SELECT * 
    FROM foo 
WHERE id NOT IN 
     (SELECT foo1.id 
      FROM foo AS foo1 
      JOIN foo AS foo2 
       ON foo2.id <= foo1.id 
      GROUP 
       BY foo1.id 
      HAVING SUM(foo2.qty1 + foo2.qty2 + foo2.qty3 + foo2.qty4) <= 57 
     ) 
; 

अनपेक्षित विकल्प बहुत अधिक कठिन है; यह करने योग्य है, लेकिन आप stored procedure का उपयोग करके बहुत बेहतर होंगे।

4

के सवाल

mysql> drop database if exists javier; 
Query OK, 1 row affected (0.02 sec) 

mysql> create database javier; 
Query OK, 1 row affected (0.01 sec) 

mysql> use javier 
Database changed 
mysql> create table mytable 
    -> (
    ->  id int not null auto_increment, 
    ->  qty1 float,qty2 float,qty3 float,qty4 float, 
    ->  primary key (id) 
    ->); 
Query OK, 0 rows affected (0.08 sec) 

mysql> insert into mytable (qty1,qty2,qty3,qty4) values 
    -> (0.0 , 0.0 , 10 , 20),(1.5 , 0.0 , 7.5 , 18), 
    -> (1.0 , 2.0 , 7.5 , 18),(0.0 , 0.5 , 5 , 13); 
Query OK, 4 rows affected (0.05 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> select * from mytable; 
+----+------+------+------+------+ 
| id | qty1 | qty2 | qty3 | qty4 | 
+----+------+------+------+------+ 
| 1 | 0 | 0 | 10 | 20 | 
| 2 | 1.5 | 0 | 7.5 | 18 | 
| 3 | 1 | 2 | 7.5 | 18 | 
| 4 | 0 | 0.5 | 5 | 13 | 
+----+------+------+------+------+ 
4 rows in set (0.00 sec) 

mysql> 

अंतिम क्वेरी जो पूरी तरह काम करता है

select BBBB.* from (select id,sums FROM (select A.id,A.sums from 
(select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
where BB.id<=AA.id) sums from mytable AA order by id) A 
INNER JOIN (SELECT 50 mylimit) B ON A.sums <= B.mylimit) AAA 
UNION 
(select A.id,A.sums from (select id,(select sum(qty1+qty2+qty3+qty4) 
from mytable BB where BB.id<=AA.id) sums from mytable AA order by id) A 
where A.sums=(select min(A.sums) sums from (select id, 
(select sum(qty1+qty2+qty3+qty4) from mytable BB where BB.id<=AA.id) sums 
from mytable AA order by id) A INNER JOIN (SELECT 50 mylimit) B 
ON A.sums >= B.mylimit))) AAAA JOIN mytable BBBB USING (id); 

अंतिम क्वेरी के पूरक कि पूरी तरह से काम करता है

select BBBB.* from mytable BBBB LEFT JOIN 
(select id,sums FROM (select A.id,A.sums from ( 
select id,(select sum(qty1+qty2+qty3+qty4) 
from mytable BB where BB.id<=AA.id) sums 
from mytable AA order by id) A INNER JOIN 
(SELECT 50 mylimit) B ON A.sums <= B.mylimit) AAA 
UNION 
(select A.id,A.sums from (select id, 
(select sum(qty1+qty2+qty3+qty4) from mytable BB 
where BB.id<=AA.id) sums from mytable AA order by id) A 
where A.sums=(select min(A.sums) sums from ( 
select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
where BB.id<=AA.id) sums from mytable AA order by id) A 
INNER JOIN (SELECT 50 mylimit) B ON A.sums >= B.mylimit))) AAAA 
USING (id) WHERE AAAA.id IS NULL; 

यहाँ से अपने नमूना डेटा लोड करते हैं के लिए 57

mysql>  select BBBB.* from (select id,sums FROM (select A.id,A.sums from 
    ->  (select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  INNER JOIN (SELECT 57 mylimit) B ON A.sums <= B.mylimit) AAA 
    ->  UNION 
    ->  (select A.id,A.sums from (select id,(select sum(qty1+qty2+qty3+qty4) 
    ->  from mytable BB where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  where A.sums=(select min(A.sums) sums from (select id, 
    ->  (select sum(qty1+qty2+qty3+qty4) from mytable BB where BB.id<=AA.id) sums 
    ->  from mytable AA order by id) A INNER JOIN (SELECT 57 mylimit) B 
    ->  ON A.sums >= B.mylimit))) AAAA JOIN mytable BBBB USING (id); 
+----+------+------+------+------+ 
| id | qty1 | qty2 | qty3 | qty4 | 
+----+------+------+------+------+ 
| 1 | 0 | 0 | 10 | 20 | 
| 2 | 1.5 | 0 | 7.5 | 18 | 
+----+------+------+------+------+ 
2 rows in set (0.00 sec) 

mysql>  select BBBB.* from mytable BBBB LEFT JOIN 
    ->  (select id,sums FROM (select A.id,A.sums from (
    ->  select id,(select sum(qty1+qty2+qty3+qty4) 
    ->  from mytable BB where BB.id<=AA.id) sums 
    ->  from mytable AA order by id) A INNER JOIN 
    ->  (SELECT 57 mylimit) B ON A.sums <= B.mylimit) AAA 
    ->  UNION 
    ->  (select A.id,A.sums from (select id, 
    ->  (select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  where A.sums=(select min(A.sums) sums from (
    ->  select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  INNER JOIN (SELECT 57 mylimit) B ON A.sums >= B.mylimit))) AAAA 
    ->  USING (id) WHERE AAAA.id IS NULL; 
+----+------+------+------+------+ 
| id | qty1 | qty2 | qty3 | qty4 | 
+----+------+------+------+------+ 
| 3 | 1 | 2 | 7.5 | 18 | 
| 4 | 0 | 0.5 | 5 | 13 | 
+----+------+------+------+------+ 
2 rows in set (0.00 sec) 

mysql> 

उत्पादन होता है यहाँ 50

mysql>  select BBBB.* from (select id,sums FROM (select A.id,A.sums from 
    ->  (select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  INNER JOIN (SELECT 50 mylimit) B ON A.sums <= B.mylimit) AAA 
    ->  UNION 
    ->  (select A.id,A.sums from (select id,(select sum(qty1+qty2+qty3+qty4) 
    ->  from mytable BB where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  where A.sums=(select min(A.sums) sums from (select id, 
    ->  (select sum(qty1+qty2+qty3+qty4) from mytable BB where BB.id<=AA.id) sums 
    ->  from mytable AA order by id) A INNER JOIN (SELECT 50 mylimit) B 
    ->  ON A.sums >= B.mylimit))) AAAA JOIN mytable BBBB USING (id); 
+----+------+------+------+------+ 
| id | qty1 | qty2 | qty3 | qty4 | 
+----+------+------+------+------+ 
| 1 | 0 | 0 | 10 | 20 | 
| 2 | 1.5 | 0 | 7.5 | 18 | 
+----+------+------+------+------+ 
2 rows in set (0.00 sec) 

mysql>  select BBBB.* from mytable BBBB LEFT JOIN 
    ->  (select id,sums FROM (select A.id,A.sums from (
    ->  select id,(select sum(qty1+qty2+qty3+qty4) 
    ->  from mytable BB where BB.id<=AA.id) sums 
    ->  from mytable AA order by id) A INNER JOIN 
    ->  (SELECT 50 mylimit) B ON A.sums <= B.mylimit) AAA 
    ->  UNION 
    ->  (select A.id,A.sums from (select id, 
    ->  (select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  where A.sums=(select min(A.sums) sums from (
    ->  select id,(select sum(qty1+qty2+qty3+qty4) from mytable BB 
    ->  where BB.id<=AA.id) sums from mytable AA order by id) A 
    ->  INNER JOIN (SELECT 50 mylimit) B ON A.sums >= B.mylimit))) AAAA 
    ->  USING (id) WHERE AAAA.id IS NULL; 
+----+------+------+------+------+ 
| id | qty1 | qty2 | qty3 | qty4 | 
+----+------+------+------+------+ 
| 3 | 1 | 2 | 7.5 | 18 | 
| 4 | 0 | 0.5 | 5 | 13 | 
+----+------+------+------+------+ 
2 rows in set (0.01 sec) 

mysql> 

के लिए उत्पादन है (SELECT 50 mylimit) सबक्वेरी में mylimit के लिए दो बार प्रत्येक संख्या निर्धारित करना याद रखें।

बताएं कि मैं इस एक मिल ...

+0

धन्यवाद :) हालांकि यह सिर्फ मेरे द्वारा प्रस्तावित सरल मामला हल करता है, जटिल नहीं;) –

+0

@ जेवियर जटिल क्या है? यदि आपका मतलब 50 की तरह किसी अन्य नंबर का उपयोग करना है, तो दोनों प्रश्नों (अंतिम और अंतिम संकलन) में '(SELECT 57 mylimit)' के साथ '(SELECT 57 mylimit)' को प्रतिस्थापित करें और वे पूरी तरह से काम करेंगे। अन्यथा, कृपया जटिल मामले की व्याख्या करें। – RolandoMySQLDBA

+0

मैं उदाहरण के द्वारा, नमूना डेटा का उपयोग करके व्याख्या करने की कोशिश करूंगा। Mylimit = 50 के साथ, क्वेरी का परिणाम आईडी = 2 के लिए देना चाहिए: qty1 = 1.5, qty2 = 0.0, qty3 = 7.5, qty4 = 11। हालांकि, आपके प्रश्न मुझे id = 2 के लिए कोई पंक्ति नहीं देते हैं। जैसा कि आप देख सकते हैं, qty4 = 11 तालिका के डेटा में नहीं है, लेकिन प्रत्येक पंक्ति पर qty1 + qty2 + qty3 + qty4 के मान जोड़ने का परिणाम है जब तक कि माइलिमिट मान तक नहीं पहुंच जाता है। यही है, जब आप जोड़ते हैं तो 50 पहुंच जाता है: row1.qty1 + row1.qty2 + row1.qty3 + row1.qty4 फिर + row2.qty1 + row2.qty2 + row2.qty3 फिर +7 जो मूल पंक्ति 2.qty4 से निकाला जाता है = 18, जो वांछित परिणाम –

4

आप init सबक्वेरी में केवल @limit चर प्रारंभ समायोजित करना चाहिए। पहली क्वेरी डेटा को सीमित करने के लिए आउटपुट करती है, सेकेंड क्वेरी इसके पूरक को आउटपुट करती है।

SELECT 
    id, 
    @qty1 as qty1, 
    @qty2 as qty2, 
    @qty3 as qty3, 
    @qty4 as qty4 
FROM quantities q, 
    (SELECT @qty1:=0.0, @qty2:=0.0, 
      @qty3:=0.0, @qty4:=0.0, 
      @limit:=50.0) init 
WHERE 
    IF(@limit > 0, 
    GREATEST(1, 
     IF(@limit-qty1 >=0, 
      @limit:=(@limit-(@qty1:=qty1)), 
      @qty1:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty2 >=0, 
      @limit:=(@limit-(@qty2:=qty2)), 
      @qty2:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty3 >=0, 
      @limit:=(@limit-(@qty3:=qty3)), 
      @qty3:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty4 >=0, 
      @limit:=(@limit-(@qty4:=qty4)), 
      @qty4:[email protected] + LEAST(@limit, @limit:=0))),0) 
; 

पूरक:

SELECT 
    id, 
    IF([email protected], qty1, [email protected]) as qty1, 
    IF([email protected], qty2, [email protected]) as qty2, 
    IF([email protected], qty3, [email protected]) as qty3, 
    IF([email protected], qty4, [email protected]) as qty4 
FROM quantities q, 
    (SELECT @qty1:=0.0, @qty2:=0.0, 
      @qty3:=0.0, @qty4:=0.0, 
      @limit:=50.0) init 
WHERE 
    IF(
    LEAST(
     IF(@limit-qty1 >=0, 
     @limit:=(@limit-(@qty1:=qty1)), 
     @qty1:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty2 >=0, 
     @limit:=(@limit-(@qty2:=qty2)), 
     @qty2:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty3 >=0, 
     @limit:=(@limit-(@qty3:=qty3)), 
     @qty3:[email protected] + LEAST(@limit, @limit:=0)), 
     IF(@limit-qty4 >=0, 
     @limit:=(@limit-(@qty4:=qty4)), 
     @qty4:[email protected] + LEAST(@limit, @limit:=0)), 
     @limit), 0, 1) 
; 
+0

धन्यवाद! यह नमूना डेटा के साथ काम करता है। मुझे अपने असली डेटा के साथ परीक्षण करने दें और मैं आपको बक्षीस के बारे में उत्तर दूंगा ... –

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