गिनती करें जहां एक पंक्ति में दो या अधिक कॉलम एक निश्चित मान से अधिक हैं [बास्केटबॉल, डबल डबल, ट्रिपल डबल]


20

मैं एक बास्केटबॉल गेम खेलता हूं जो एक डेटाबेस फ़ाइल के रूप में अपने आंकड़ों को आउटपुट करने की अनुमति देता है, इसलिए कोई इससे उन आंकड़ों की गणना कर सकता है जो गेम में लागू नहीं होते हैं। अब तक मुझे उन आंकड़ों को शांत करने में कोई समस्या नहीं है जो मुझे चाहिए थे, लेकिन अब मैं एक समस्या में चला गया हूं: अपने खेल के आंकड़ों से सीज़न में बनाए गए खिलाड़ी से दोगुने और / या ट्रिपल युगल की गिनती।

एक डबल डबल और ट्रिपल डबल की परिभाषा इस प्रकार है:

दुगुना दुगुना:

एक डबल-डबल को एक प्रदर्शन के रूप में परिभाषित किया गया है जिसमें एक खिलाड़ी दो सांख्यिकीय श्रेणियों में दो अंकों की कुल संख्या को जमा करता है- अंक, रिबॉइड, सहायता, चोरी और अवरुद्ध शॉट्स - एक खेल में।

तिगुना दोगुना:

ट्रिपल-डबल को एक प्रदर्शन के रूप में परिभाषित किया जाता है, जिसमें एक खिलाड़ी पांच सांख्यिकीय श्रेणियों में से तीन अंकों में एक डबल अंकों की कुल संख्या जमा करता है- अंक, रिबॉइड, सहायता, चोरी और अवरुद्ध शॉट्स - एक खेल में।

चौगुना-डबल (स्पष्टीकरण के लिए जोड़ा गया)

एक चौगुनी-डबल को एक प्रदर्शन के रूप में परिभाषित किया जाता है जिसमें एक खिलाड़ी पांच सांख्यिकीय श्रेणियों में से चार में एक दोहरे अंक की कुल संख्या जमा करता है- अंक, रिबॉइड, सहायता, चोरी और अवरुद्ध शॉट्स - एक खेल में।

"PlayerGameStats" तालिका में प्रत्येक खिलाड़ी द्वारा खेले जाने वाले खेल के लिए आंकड़े संग्रहीत किए गए हैं और निम्नानुसार हैं:

CREATE TABLE PlayerGameStats AS SELECT * FROM ( VALUES
  ( 1, 1,  1, 'Nuggets',    'Cavaliers',  6,  8,  2, 2,  0 ),
  ( 2, 1,  2, 'Nuggets',     'Clippers', 15,  7,  0, 1,  3 ),
  ( 3, 1,  6, 'Nuggets', 'Trailblazers', 11, 11,  1, 2,  1 ),
  ( 4, 1, 10, 'Nuggets',    'Mavericks',  8, 10,  2, 2, 12 ),
  ( 5, 1, 11, 'Nuggets',       'Knicks', 23, 12,  1, 0,  0 ),
  ( 6, 1, 12, 'Nuggets',         'Jazz',  8,  8, 11, 1,  0 ),
  ( 7, 1, 13, 'Nuggets',         'Suns',  7, 11,  2, 2,  1 ),
  ( 8, 1, 14, 'Nuggets',        'Kings', 10, 15,  0, 3,  1 ),
  ( 9, 1, 15, 'Nuggets',        'Kings',  9,  7,  5, 0,  4 ),
  (10, 1, 17, 'Nuggets',      'Thunder', 13, 10, 10, 1,  0 )
) AS t(id,player_id,seasonday,team,opponent,points,rebounds,assists,steals,blocks);

जिस आउटपुट को मैं प्राप्त करना चाहता हूं वह इस प्रकार है:

| player_id |    team | doubleDoubles | tripleDoubles |
|-----------|---------|---------------|---------------|
|         1 | Nuggets |             4 |             1 |

एकमात्र समाधान जो मुझे अब तक मिला है वह इतना भयानक है कि यह मुझे आश्चर्यचकित करता है ...; ओ) ... यह इस तरह दिखता है:

SELECT 
  player_id,
  team,
  SUM(CASE WHEN(points >= 10 AND rebounds >= 10) OR
               (points >= 10 AND assists  >= 10) OR
               (points >= 10 AND steals   >= 10) 
                THEN 1 
                ELSE 0 
      END) AS doubleDoubles
FROM PlayerGameStats
GROUP BY player_id

... और अब आप इसे पढ़कर शायद पुकिंग भी कर रहे हैं (या मुश्किल से हंस रहे हैं)। मैंने वह सब कुछ भी नहीं लिखा, जो सभी डबल डबल संयोजनों को प्राप्त करने के लिए आवश्यक होगा, और ट्रिपल डबल्स के लिए केस स्टेटमेंट को छोड़ दिया क्योंकि यह और भी हास्यास्पद है।

क्या ऐसा करने के लिए इससे अच्छा तरीका है? या तो तालिका संरचना के साथ या मेरे पास एक नई तालिका संरचना है (मैं तालिका को रूपांतरित करने के लिए एक स्क्रिप्ट लिख सकता हूं)।

मैं MySQL 5.5 या PostgreSQL 9.2 का उपयोग कर सकता हूं।

यहाँ उदाहरण डेटा और मेरे भयानक समाधान के साथ SqlFiddle की एक कड़ी है जो मैंने ऊपर पोस्ट की है: http://sqlfiddle.com/#! 2 / af6101 /3

ध्यान दें कि मुझे वास्तव में चौगुनी-युगल में दिलचस्पी नहीं है (ऊपर देखें) क्योंकि वे उस गेम में नहीं होते हैं जो मैं जानता हूं कि मैं जहां तक ​​खेलता हूं, लेकिन यह एक प्लस होगा यदि क्वेरी को आसानी से विस्तार के बिना फिर से लिखना संभव है चौगुनी-युगल के लिए।

जवाबों:


10

पता नहीं अगर यह सबसे अच्छा तरीका है। मैंने पहली बार यह पता लगाने के लिए चयन किया था कि क्या एक स्टेटमेंट डबल डिजिट का है और यदि यह है तो इसे 1 असाइन करें। प्रति गेम दोहरे अंकों की कुल संख्या का पता लगाने के लिए उन सभी को सम्‍मिलित करें। वहाँ से बस सभी युगल और त्रिगुणों को जोड़ते हैं। काम करने लगता है

select a.player_id, 
a.team, 
sum(case when a.doubles = 2 then 1 else 0 end) as doubleDoubles, 
sum(case when a.doubles = 3 then 1 else 0 end) as tripleDoubles
from
(select *, 
(case when points > 9 then 1 else 0 end) +
(case when rebounds > 9 then 1 else 0 end) +
(case when assists > 9 then 1 else 0 end) +
(case when steals > 9 then 1 else 0 end) +
(case when blocks > 9 then 1 else 0  end) as Doubles
from PlayerGameStats) a
group by a.player_id, a.team

नमस्ते, आप समाधान के लिए धन्यवाद। मुझे वास्तव में यह पसंद है। बिल्कुल वही करता है जो मैं चाहता हूं और बहुत अधिक लेखन के बिना चौगुनी-डबल और क्विंटुपल-युगल को आसानी से शामिल करने के लिए विस्तार योग्य है। क्या यह अभी के लिए स्वीकृत उत्तर देगा। :)
केथ

मुझे आपका कोड पसंद है, लेकिन आप इसे और भी छोटा होने के लिए हैक कर सकते हैं। CASEबूलियन एक्सप्रेशंस 1 का मूल्यांकन करते समय सही और 0 गलत होने पर स्टेटमेंट का उपयोग करने की आवश्यकता नहीं है । मैंने इसे नीचे दिए गए मेरे उत्तर के साथ जोड़ा है क्योंकि आप यहाँ टिप्पणी में पूर्ण SQL कोड ब्लॉक नहीं कर सकते हैं।
जोशुआ ह्यूबर

धन्यवाद जोशुआ। पूरी तरह से नजरअंदाज कर दिया और यह बहुत बेहतर लग रहा है।
SQLChao

1
@JoshuaHuber राइट लेकिन फिर क्वेरी केवल MySQL में काम करेगी। का उपयोग करना CASEऔर SUM/COUNTयह Postgres पर भी काम करने की अनुमति देता है।
ypercube y

@ypercube: वास्तव में, पोस्टग्रेज में बूलियन को जोड़ना भी काम करता है। आपको केवल स्पष्ट रूप से डालना होगा। लेकिन CASEआमतौर पर एक छोटा सा तेजी से है। मैंने कुछ अन्य छोटे सुधारों के साथ एक डेमो जोड़ा।
एरविन ब्रान्डसेट्टर

7

इसे आज़माएं (MySQL 5.5 पर मेरे लिए काम किया गया):

SELECT 
  player_id,
  team,
  SUM(
    (   (points   >= 10)
      + (rebounds >= 10)
      + (assists  >= 10)
      + (steals   >= 10)
      + (blocks   >= 10) 
    ) = 2
  ) double_doubles,
  SUM(
    (   (points   >= 10)
      + (rebounds >= 10)
      + (assists  >= 10)
      + (steals   >= 10)
      + (blocks   >= 10) 
    ) = 3
  ) triple_doubles
FROM PlayerGameStats
GROUP BY player_id, team

या उससे भी छोटा, अपने जवाब से जेसीएचओ के कोड को स्पष्ट रूप से काटकर, लेकिन अनावश्यक CASEबयानों को हटाने के बाद से बूलियन एक्सपोर्ट {1,0} का मूल्यांकन करता है जब {सही, गलत}:

select a.player_id, 
a.team, 
sum(a.doubles = 2) as doubleDoubles, 
sum(a.doubles = 3) as tripleDoubles
from
(select *, 
(points > 9) +
(rebounds > 9) +
(assists > 9) +
(steals > 9) +
(blocks > 9) as Doubles
from PlayerGameStats) a
group by a.player_id, a.team

टिप्पणियों के आधार पर कि उपर्युक्त कोड PostgreSQL में नहीं चलेगा क्योंकि यह बूलियन + बूलियन करना पसंद नहीं करता है। मुझे अभी भी पसंद नहीं है CASE। यहाँ पोस्टग्रेएसक्यूएल (9.3) पर एक तरीका है, के लिए कास्टिंग द्वारा int:

select a.player_id, 
a.team, 
sum((a.doubles = 2)::int) as doubleDoubles, 
sum((a.doubles = 3)::int) as tripleDoubles
from
(select *, 
(points > 9)::int +
(rebounds > 9)::int +
(assists > 9)::int +
(steals > 9)::int +
(blocks > 9)::int as Doubles
from PlayerGameStats) a
group by a.player_id, a.team

@ypercube, अच्छी बात और धन्यवाद। सिर्फ इतना पूछा था कि उपरोक्त प्रश्न पर टिप्पणी के रूप में सटीक स्पष्टीकरण। शब्दार्थ। मेरा मानना ​​है कि हॉकी में चार लक्ष्यों को अभी भी "एक हैट ट्रिक खींचना" माना जाता है, लेकिन गेंदबाजी में लगातार चार स्ट्राइक को "टर्की" उचित नहीं माना जा सकता है, बल्कि यह "क्वाड" है। मैं प्रत्येक खेल के शब्दार्थ पर कोई विशेषज्ञ नहीं हूँ। आप निर्णय लेते हैं और चुनते हैं =या >=फिट होते हैं।
जोशुआ ह्यूबर

आपके समाधान के लिए धन्यवाद। निश्चित रूप से वही करता है जो मैं चाहता हूं। इसके अलावा आपके द्वारा प्रदान की गई जेसीएचओ के लघु संस्करण की तरह।
कीथ

1
हालांकि, पोस्टग्रेक्यूएल में बूलियन जोड़ना काम नहीं करेगा, इसे ध्यान में रखें।
क्रेग रिंगर

@ क्रैगरिंगर - यह इंगित करने के लिए धन्यवाद। जब से यह सामान्य रूप से SQL में आता है और विशेष रूप से PostgreSQl में कान के पीछे मैं अभी भी हरा हूं, यह मेरे लिए मूल्यवान जानकारी है। :)
केथ

1
@ क्रेगिंगर अच्छा है, लेकिन मुझे नहीं लगता कि MySQL का समर्थन करता है CAST(... AS int) ( stackoverflow.com/questions/12126991/… )। MySQL कर सकते हैं CAST(... AS UNSIGNED), जो इस क्वेरी में काम करता है, लेकिन PostgreSQL नहीं कर सकता। सुनिश्चित नहीं है कि CASTपोर्टेबिलिटी के लिए दोनों एक समान है। सबसे खराब मामला, CASEपोर्टेबिलिटी सर्वोपरि होने पर अंत में अटक सकता है ।
जोशुआ ह्यूबर

6

यहाँ एक और समस्या है।

जिस तरह से मैं इसके बारे में सोचता हूं, आप वर्तमान समस्या के लिए आवश्यक डेटा के साथ काम कर रहे हैं, इसलिए ऐसा करने के लिए पहली बात यह है कि यह अनपेक्षित है। दुर्भाग्य से PostgreSQL ऐसा करने के लिए अच्छे उपकरण प्रदान नहीं करता है, इसलिए PL / PgSQL में गतिशील SQL पीढ़ी में आए बिना, हम कम से कम कर सकते हैं:

SELECT player_id, seasonday, 'points' AS scoretype, points AS score FROM playergamestats
UNION ALL
SELECT player_id, seasonday, 'rebounds' AS scoretype, rebounds FROM playergamestats
UNION ALL
SELECT player_id, seasonday, 'assists' AS scoretype, assists FROM playergamestats
UNION ALL
SELECT player_id, seasonday, 'steals' AS scoretype, steals FROM playergamestats
UNION ALL
SELECT player_id, seasonday, 'blocks' AS scoretype, blocks FROM playergamestats

यह डेटा को अधिक निंदनीय रूप में रखता है, हालांकि यह निश्चित है कि सुंदर नहीं है। यहाँ मुझे लगता है कि (खिलाड़ी_ समुद्र का किनारा) खिलाड़ियों की विशिष्ट पहचान करने के लिए पर्याप्त है, अर्थात खिलाड़ी आईडी टीमों में अद्वितीय है। यदि ऐसा नहीं है, तो आपको एक अद्वितीय कुंजी प्रदान करने के लिए पर्याप्त अन्य जानकारी शामिल करने की आवश्यकता होगी।

उस अनपेक्षित डेटा के साथ अब इसे उपयोगी तरीके से फ़िल्टर और एकत्र करना संभव है, जैसे:

SELECT
  player_id,
  count(CASE WHEN doubles = 2 THEN 1 END) AS doubledoubles,
  count(CASE WHEN doubles = 3 THEN 1 END) AS tripledoubles
FROM (
    SELECT
      player_id, seasonday, count(*) AS doubles
    FROM
    (
        SELECT player_id, seasonday, 'points' AS scoretype, points AS score FROM playergamestats
        UNION ALL
        SELECT player_id, seasonday, 'rebounds' AS scoretype, rebounds FROM playergamestats
        UNION ALL
        SELECT player_id, seasonday, 'assists' AS scoretype, assists FROM playergamestats
        UNION ALL
        SELECT player_id, seasonday, 'steals' AS scoretype, steals FROM playergamestats
        UNION ALL
        SELECT player_id, seasonday, 'blocks' AS scoretype, blocks FROM playergamestats
    ) stats
    WHERE score >= 10
    GROUP BY player_id, seasonday
) doublestats
GROUP BY player_id;

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

तो यह एक गंभीर सुझाव की तुलना में "हे, क्या तुमने सोचा" था। लक्ष्य यह था कि एसक्यूएल को मॉडल स्टेटमेंट के अनुरूप बनाने के लिए मॉडल को सीधा किया जाए, बजाय इसके कि इसे जल्दी बनाया जाए।


यह आपके MySQL- उन्मुख एसक्यूएल में साने बहु-मूल्यवान आवेषण और एएनएसआई के उद्धरण के उपयोग से बहुत आसान बना दिया गया था। धन्यवाद; एक बार के लिए backticks नहीं देखना अच्छा है। मुझे जो कुछ बदलना था वह सिंथेटिक की जेनरेशन थी।


यह मेरे मन में था की तरह है।
कॉलिन टी हार्ट

1
इस समाधान पोस्टिंग के लिए धन्यवाद। मेरी समस्याओं को कुछ इस तरह से लागू कर रहा था जैसा कि @ Colin'tHart ने ऊपर सुझाया है (ऐसा कुछ पहले कभी नहीं किया था, लेकिन लगता है कि कुछ अन्य आँकड़े जो मैं भविष्य में शांत करना चाहता हूं) के लिए बहुत उपयोगी है। यह दिलचस्प है कि मेरे वांछित उत्पादन को पूरा करने के कितने तरीके हैं। आज निश्चित रूप से बहुत कुछ सीखा है।
कीथ

1
अधिक जानने के लिए, explain analyzeक्वेरी योजना (या MySQL समतुल्य) और यह पता करें कि वे क्या करते हैं और कैसे :)
क्रेग रिंगर

@ क्रैगरिंगर - धन्यवाद। अच्छी सलाह। वास्तव में इस तरह के सभी समाधान अब तक प्रदान किए गए (मैंने SqlFiddles "दृश्य निष्पादन योजना" का उपयोग किया)। लेकिन मुझे निश्चित रूप से आउटपुट पढ़ते समय "यह पता लगाने की आवश्यकता है कि वे सभी क्या करते हैं और कैसे" भाग पर काम करते हैं। = ओ
केथ

6

MySQL के लिए @Joshua क्या प्रदर्शित करता है, पोस्टग्रैज में भी काम करता है। Booleanमूल्यों को integerजोड़ा और जोड़ा जा सकता है । हालांकि कलाकारों को स्पष्ट होने की आवश्यकता है। बहुत कम कोड के लिए बनाता है:

SELECT player_id, team
     , count(doubles = 2 OR NULL) AS doubledoubles
     , count(doubles = 3 OR NULL) AS tripledoubles
FROM  (
   SELECT player_id, team,
          (points   > 9)::int +
          (rebounds > 9)::int +
          (assists  > 9)::int +
          (steals   > 9)::int +
          (blocks   > 9)::int AS doubles
   FROM playergamestats
   ) a
GROUP  BY 1, 2;

हालांकि, CASE- भले ही अधिक क्रिया - आमतौर पर थोड़ा तेज है। और अधिक पोर्टेबल, अगर यह बात होनी चाहिए:

SELECT player_id, team
     , count(doubles = 2 OR NULL) AS doubledoubles
     , count(doubles = 3 OR NULL) AS tripledoubles
FROM  (
   SELECT player_id, team,
          CASE WHEN points   > 9 THEN 1 ELSE 0 END +
          CASE WHEN rebounds > 9 THEN 1 ELSE 0 END +
          CASE WHEN assists  > 9 THEN 1 ELSE 0 END +
          CASE WHEN steals   > 9 THEN 1 ELSE 0 END +
          CASE WHEN blocks   > 9 THEN 1 ELSE 0 END AS doubles
   FROM playergamestats
   ) a
GROUP  BY 1, 2;

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



2

पूर्णांक विभाजन और बाइनरी का उपयोग करना

SELECT player_id
     , team
     , SUM(CASE WHEN Doubles = 2 THEN 1 ELSE 0 END) DoubleDouble
     , SUM(CASE WHEN Doubles = 3 THEN 1 ELSE 0 END) TripleDouble
FROM   (SELECT player_id
             , team
             , (BINARY (points DIV 10) > 0)
             + (BINARY (rebounds DIV 10) > 0)
             + (BINARY (assists DIV 10) > 0)
             + (BINARY (steals DIV 10) > 0)
             + (BINARY (blocks DIV 10) > 0)
             AS Doubles
        FROM   PlayerGameStats) d
GROUP BY player_id, team

1

बस @ क्रेग रिंगर्स संस्करण की विविधता को छोड़ना चाहता हूं यहां मुझे दुर्घटना से मिला, शायद यह भविष्य में किसी के लिए उपयोगी हो।

कई UNION ALL के बजाय यह अनावश्यक और सरणी का उपयोग करता है। प्रेरणा के स्रोत: /programming/1128737/unpivot-and-postgresql


SELECT
  player_id,
  count(CASE WHEN doubles = 2 THEN 1 END) AS doubledoubles,
  count(CASE WHEN doubles = 3 THEN 1 END) AS tripledoubles
FROM (
    SELECT
      player_id, seasonday, count(*) AS doubles
    FROM
    (
        SELECT 
          player_id, 
          seasonday,
          unnest(array['Points', 'Rebounds', 'Assists', 'Steals', 'Blocks']) AS scoretype,
          unnest(array[Points, Rebounds, Assists, Steals, Blocks]) AS score
        FROM PlayerGameStats
    ) stats
    WHERE score >= 10
    GROUP BY player_id, seasonday
) doublestats
GROUP BY player_id;

एसक्यूएल फिडल: http://sqlfiddle.com/# -12 / 4980b /3

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