2012-03-28 10 views
5

द्वारा रैंक की गणना करने के लिए क्वेरी मैं सिम्फनी 1.4 और सिद्धांत 1.2 ओआरएम में एक ऐप बना रहा हूं। मैं सिद्धांत ओआरएम के लिए काफी नया हूं और इसे लटका रहा हूं लेकिन मैं इस समस्या को हल नहीं कर सकता।सिमफनी सिद्धांत क्वेरी एक समूह के बाद सबक्वायरी

मेरे पास उपयोगकर्ता स्कोर (mbScoreByGenre) की एक तालिका है जहां एक उपयोगकर्ता आईडी में एक parent_genre के लिए उपयोगकर्ता स्कोर के एकाधिक रिकॉर्ड हो सकते हैं। यानी - कई

मेरा लक्ष्य किसी दिए गए parent_genre_id और user_id के लिए अपने संचयी स्कोर के आधार पर किसी विशेष उपयोगकर्ता के रैंक को ढूंढना है। मेरा रैंकिंग एल्गोरिदम एक सबक्वायरी का उपयोग करता है और मुझे काम करने वाली एक सिद्धांत क्वेरी बनाने में बहुत परेशानी हो रही है।

यहाँ mbScoreByGenre के लिए मेरे सिद्धांत स्कीमा है

mbScoreByGenre: 
    actAs: 
    Timestampable: ~  
    columns: 

    id:     { type: integer, primary: true, autoincrement: true } 
    user_id:   { type: integer, notnull: true } 
    genre_id:   { type: integer, notnull: true } 
    parent_genre_id: { type: integer, notnull: true } 
    score:    { type: float, notnull: true, default: 0 } 

A. सबसे पहले मैं इस तरह कुछ करने की कोशिश:

$q = Doctrine_Query::create() 
    ->select('((SELECT COUNT(1) AS num 
     FROM 
     (SELECT SUM(mbScoreByGenre.score) 
     WHERE SUM(mbScoreByGenre.score) > SUM(s.score) 
     AND mbScoreByGenre.parent_genre_id = '.$genre['parent_id'].' 
     AND s.parent_genre_id = '.$genre['parent_id'].' 
     GROUP BY mbScoreByGenre.user_id 
     ) + 1) AS rank') 
    ->from('mbScoreByGenre s') 
    ->where('s.user_id = ?', array($user_id)) 
    ->groupBy('s.user_id') 
    ->orderBy('rank'); 

but I got the following error Fatal error: Maximum function nesting level of '100' reached, aborting! in \lib\vendor\symfony-1.4.14\lib\plugins\sfDoctrinePlugin\lib\vendor\doctrine\Doctrine\Query\Tokenizer.php on line 303. I don't understand how to build the subquery so that it works.

बी तो फिर मैं बदल गया है और एक अलग दृष्टिकोण की कोशिश की

$q = new Doctrine_RawSql(); 
$q ->addComponent('s', 'mbScoreByGenre') 
    ->select('COUNT({*}) AS {rank}') 
    ->from('(SELECT SUM(s.score) AS total_score 
     FROM mb_score_by_genre s 
     WHERE s.parent_genre_id = '.$genre['parent_id'].' 
     GROUP BY s.user_id) 
      ') 
    ->where('total_score >= (
     SELECT SUM(s.score) 
     FROM mb_score_by_genre s 
     WHERE s.parent_genre_id = '.$genre['parent_id'].' 
     AND s.user_id = '.$user_id.' 
     GROUP BY s.user_id 
    )'); 

लेकिन मुझे यह त्रुटि मिली: एसक्यूएल क्वेरी में सभी चयनित फ़ील्ड प्रारूप तालिका में होना चाहिए Alas.fieldName। जिस कारण से मैंने एक डॉक्टरेट_आरओएसएसक्यूएल का उपयोग किया है, मैंने पढ़ा है कि सिद्धांत 1.2 से उपखंडों का समर्थन नहीं करता है। इस दृष्टिकोण के लिए मैं तालिका Alias.fieldName प्रारूप में "total_score" कॉलम को संदर्भित करने का तरीका नहीं समझ सका। क्या मुझे एक रिक्त घटक जोड़ना है जो "total_score" के लिए लौटाई गई सबक्वायरी तालिका को संदर्भित करता है?

सी। अंत में मैंने केवल एक क्वेरी क्वेरी के रूप में सबक्वायरी चलाने की कोशिश की और क्वेरी द्वारा लौटाई गई सामग्रियों की पंक्तियों की गणना करके रैंक की गणना की।

$q = Doctrine_Query::create() 
    ->select('SUM(s.score)') 
    ->from('mbScoreByGenre s') 
    ->where('s.parent_genre_id = ?', $genre['parent_id']) 
    ->andWhere('SUM(s.score) > (
     SELECT SUM(p.score) 
     FROM mbScoreByGenre p 
     WHERE p.parent_genre_id = '.$genre['parent_id'].' 
     AND p.user_id = '.$user_id.' 
     GROUP BY p.user_id 
    )') 
    ->groupBy('s.user_id'); 

    $result = $q->execute(); 

लेकिन यह मुझे त्रुटि देता है:

SQLSTATE[HY000]: General error: 1111 Invalid use of group function. Is it because groupBy('s.user_id') and GROUP BY p.user_id, both p and s refer to the same model?

मैं जवाब के लिए वेब परिशोध की एक टन कर दिया है, लेकिन मैं 3 दृष्टिकोण से किसी के लिए जवाब मिल नहीं कर पा रहे।

कोई भी मदद महान होगी। इसकी प्रशंसा करना।

+0

51 विचारों और कोई प्रतिक्रियाएं तो आपकी क्वेरी कुछ इस तरह देखना चाहिए? क्या प्रश्न कुछ और स्पष्ट करने के लिए मैं कर सकता हूं? कोई भी सहायताकाफी प्रशंसनीय होगी। – frankp221

उत्तर

2

शायद, मुझे वास्तव में समझ में नहीं आया कि आपको वास्तव में क्या चाहिए, लेकिन क्या आपने क्लॉज है? जहां खंड एसयूएम() जैसे कुल कार्यों का समर्थन नहीं करता है। मैं इस कोड की कोशिश की और यह काम किया है और कुछ मान लौट आए, लेकिन मुझे यकीन है कि के लिए नहीं कह सकता है कि अगर यह तुम क्या जरूरत है:

$q = Doctrine_Query::create() 
    ->select('count(*)') 
    ->from('mbScoreByGenre s') 
    ->where('s.parent_genre_id = ?', $genre['parent_id']) 
    ->having("SUM(s.score) > (
    SELECT SUM(p.score) 
    FROM mbScoreByGenre p 
    WHERE p.parent_genre_id = {$genre['parent_id']} 
     AND p.user_id = {$user_id})") 
->groupBy('s.user_id'); 

$result = $q->execute(array(), Doctrine::HYDRATE_SCALAR); 
var_dump($result); 

यदि यह नहीं है कि तुम क्या जरूरत है - और अधिक सटीक समझाने की कोशिश।

+0

बहुत बहुत धन्यवाद starl1ng, मुद्दा यह था कि WHERE कुल कार्यों का समर्थन नहीं करता है। मुझे समूह को कहां से पहले रखना था। परिणामस्वरूप तालिका मुझे उन सभी रिकॉर्ड्स की एक सूची देती है जो वर्तमान उपयोगकर्ता_आईडी से आगे हैं। रैंकिंग पाने के लिए, मैं बस पंक्तियों की गिनती करता हूं और जोड़ता हूं 1. धन्यवाद। – frankp221

0

कच्चे एसक्यूएल का उपयोग करके आपको स्थितियों (या आपके मामले में होने) में सबक्विरी घोंसला नहीं करना चाहिए। इसके बजाय subquery के बारे में सिद्धांत बताने के लिए createSubquery() का उपयोग करें। यह आपको अधिक जटिल परिदृश्यों में भी मदद करेगा जहां सिद्धांत सिर्फ गहराई से कच्चे एसक्यूएल प्रश्नों को संभाल नहीं सकता है।

$q = Doctrine_Query::create() 
    ->select('count(*)') 
    ->from('mbScoreByGenre s') 
    ->where('s.parent_genre_id = ?', $genre['parent_id']) 
    ->groupBy('s.user_id') 
; 

$subquery = $q->createSubquery() 
    ->select("SUM(p.score)") 
    ->from("FROM mbScoreByGenre p") 
    ->where("p.parent_genre_id = ?", $genre['parent_id']) 
    ->andWhere("p.user_id = ?", $user_id) 
; 

$q->having("SUM(s.score) > (".$subquery->getDql().")"); 

एक और उदाहरण यहां पाया जा सकता:

http://www.philipphoffmann.de/2012/08/taming-doctrine-subqueries/

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