2013-07-22 25 views
8

उदाहरण के लिए, मैं निम्न तालिका परिभाषाएं हैं:मैं स्लिम में कुल प्रश्न कैसे कर सकता हूं?

object Houses extends Table[Long]("Houses") { 
    def id = column[Long]("id") 
    def * = id 
} 
object Rooms extends Table[(Long, Long)]("Rooms") { 
    def id = column[Long]("id") 
    def houseId = column[Long]("houseId") 
    def size = column[Int]("size") 
    def * = id ~ houseId ~ size 
} 

और मैं प्रत्येक घर के लिए सबसे बड़ा कक्ष का चयन करना चाहते।

मैं निम्नलिखित चाल के साथ आया था:

val query = { 
    (r1, r2) <- Rooms leftJoin Rooms on ((r1,r2) => 
    r1.houseId === r2.houseId && r1.size > r2.size 
) 
    if r2.id.isNull 
} yield r1 

यह मैं क्या जरूरत है, लेकिन, बदसूरत पूरी तरह से पढ़ने योग्य नहीं है, और प्रदर्शन को चोट लगती है। मैंने क्वेरी पर groupBy का उपयोग करने की कोशिश की, लेकिन ऐसा लगता है कि मैं कुछ मूल अवधारणा को गलत समझ रहा हूं - मुझे सही प्रकार नहीं मिल सकते हैं।

क्या स्लिम में ऐसी कुल क्वेरी करने का कोई बेहतर तरीका है?

उत्तर

8

सबसे पहले, इस प्रकार की क्वेरी सादे एसक्यूएल में पूरी तरह से सरल नहीं है। स्लिक GroupBy अंत में एसक्यूएल ग्रुप द्वारा करने के लिए अनुवाद, तो यह उपयोग करने के लिए हम द्वारा समूह के साथ एक SQL क्वेरी की जरूरत है

ऐसा ही एक प्रश्न की तरह

SELECT r2.* FROM 
    (SELECT r.houseId, MAX(size) as size FROM Rooms r GROUP BY r.houseId) mx 
    INNER JOIN 
    Rooms r2 on r2.size = mx.size and r2.houseId = mx.houseId 

दिखाई दे सकता है यह अब चालाक के लिए अनुवाद किया जा सकता

val innerQuery = Query(Rooms).groupBy(_.houseId).map { 
    case (houseId, rows) => (houseId, rows.map(_.size).max) 
} 

val query = for { 
    (hid, max) <- innerQuery 
    r <- Rooms if r.houseId === hid && r.size === max 
} yield r 

हालांकि मुझे स्लिम के मौजूदा संस्करण में अन्य प्रश्नों में उपयोग की गई समेकित क्वेरी के साथ समस्याएं थीं।

लेकिन क्वेरी का उपयोग करके एक ग्रुप के बिना लिखा जा सकता है मौजूद है

SELECT r.* FROM Rooms r 
    WHERE NOT EXISTS (
    SELECT r2.id FROM Rooms r2 WHERE r2.size > r.size and r2.houseId = r.houseId) 

यह फिर चालाक

val query = for { 
    r <- Rooms 
    if !Query(Rooms).filter(_.houseId === r.houseId).filter(_.size > r.size).exists 
} yield r 

एक अन्य विकल्प के लिए अनुवाद किया जा सकता शायद window functions के उपयोग होगा, लेकिन मैं कर सकते हैं ' टी वास्तव में उन लोगों के साथ आपकी मदद नहीं करता है और मुझे नहीं लगता कि स्लिम उनके साथ काम कर सकता है।

(ध्यान दें कि मेरे पास स्कैला कंपाइलर नहीं है इसलिए कोड में त्रुटियां हो सकती हैं)

+0

धन्यवाद! 'अस्तित्व' वाला संस्करण वास्तव में बहुत तेज है और 30x कम पंक्तियों के माध्यम से चलता है। – Rogach

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

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