Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Progressive Sums

Îåêßíçóå áðü ôï ìÝëïò Thiseas. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 11-06-2007, 00:23. Υπάρχουν 1 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  09-06-2007, 18:44 32803

    Progressive Sums

    Συχνά, σε πολλές αναφορές μας παρουσιάζεται το πρόβλημα να υπολογίσουμε σε έναν πίνακα, προοδευτικά αθροίσματα.

    Π.χ.
    Έστω οτι έχω τον πίνακα CustomerTrans
    ΛΟΓΑΡΙΑΜΟΣ     ΕΤΟΣ    ΜΗΝΑΣ  ΧΡΕΩΣΗ   ΠΙΣΤΩΣΗ    ΥΠΟΛΟΙΠΟ
    30.00.001      2007      01    100        30          70
    30.00.001      2007      02    500        20         480
    30.00.001      2007      02     50        70         -20
    30.00.001      2007      03    100        60          40

    Ζητήται μία ακόμα στήλη: Το προοδευτικό άθροισμα του υπολοίπου ανά λογ/μό, οικονομικό έτος και μήνα (το άθροισμα του τρέχοντος υπολοίπου + το άθροισμα όλων των προηγούμενωνυπολοίπων):
    ΛΟΓΑΡΙΑΜΟΣ     ΕΤΟΣ    ΜΗΝΑΣ  ΧΡΕΩΣΗ   ΠΙΣΤΩΣΗ    ΥΠΟΛΟΙΠΟ   ΠΡΟΟΔΕΥΤΙΚΟ ΑΘ.
    30.00.001      2007      00      0         0           0           0         << από μεταφορά
    30.00.001      2007      01    100        30          70          70
    30.00.001      2007      02    500        20         480         550
    30.00.001      2007      02     50        70         -20         530
    30.00.001      2007      03    100        60          40         570


    Το ερώτημα είναι πως θα υπολογίσουμε το Προοδευτικό Άθροισμα χωρίς cursor.
    Μια λύση είναι:
    update CustomerTrans
    set [ΠΡΟΟΔΕΥΤΙΚΟ ΑΘ.] = (select sum(C2.[ΥΠΟΛΟΙΠΟ]) 
                             from CustomerTrans C2
                             where C2.[ΛΟΓΑΡΙΑΣΜΟΣ] = CustomerTrans.[ΛΟΓΑΡΙΑΣΜΟΣ] and
                                   C2.[ΕΤΟΣ] = CustomerTrans.[ΕΤΟΣ] and
                                   C2.[ΜΗΝΑΣ] <= CustomerTrans.[ΜΗΝΑΣ])

    Από πλευράς Performance... πιστεύετε οτι είναι "the best way"?


    Nothing to declare...
  •  11-06-2007, 00:23 32822 σε απάντηση της 32803

    Απ: Progressive Sums

    Βασικά, ο cursor είναι πιο γρήγορος από το Update στην περίπτωση του running sum. Ο λόγος είναι ότι ο cursor διαβάζεις τα δεδομένα μόνο μία φορά, έχοντας πολυπλοκότητα n, όπου n ο αριθμός των εγγραφών. Το select διαβάζει τα δεδομένα μία φορά για κάθε εγγραφή, έχοντας έτσι πολυπλοκότητα n². Ο cursor έχει κάποιο overhead σε σχέση με το update, οπότε για μικρό αριθμό εγγραφών το update είναι γρηγορότερο. Για μεγαλύτερο αριθμό εγγραφών όμως, ο cursor είναι γρηγορότερος.

    Ευτυχώς υπάρχει και ακόμα πιο γρήγορη και μαζεμένη λύση, αν χρησιμοποιήσεις ένα SQL CLR procedure ή SQL CLR function. Σε αυτή την περίπτωση έχεις βελτίωση σε σχέση με τον cursor κατά 25% περίπου. Κοίτα το post του Adam Machanic, "Running Sums Yet Again: SQL CLR Saves the Day". Υπάρχει πάντως και η λύση να κάνεις το άθροισμα στον client. Κάποια εργαλεία reporting υποστηρίζουν τη δημιουργία running totals, ενώ ο υπολογισμός του running total στον client π.χ. για ένα datatable απαιτεί ένα μόνο iteration των δεδομένων. Το μόνο που χρειάζεται είναι το datatable να περιέχει τα επιμέρους αθροίσματα. Συνήθως όμως αυτή την πληροφορία τη στέλνει κανείς μαζί με το running sum, οπότε δεν έχει ουσιαστική διαφορά. Ίσα-ίσα, επειδή αποφεύγεις το βήμα υπολογισμού και τους cursors στον server, το συνολικό query μπορεί να πάρει λιγότερο χρόνο αν φτιάξεις το running total στον client.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems