APPLY relational operator


Ένας από τους κυριότερους λόγους που πολλοί developers καταφεύγουν στους cursors όταν γράφουν T-SQL κώδικα είναι η αδυναμία να σκεφτούν τη λύση του προβλήματος με set-oriented τρόπο. Μια κλασική περίπτωση που συμβαίνει αυτό είναι το «θέλω για κάθε εγγραφή από τον πίνακα Χ να συμβαίνει κάτι στο πίνακα Υ».

Ο APPLY operator είναι ένας νέος relational operator που έρχεται να βοηθήσει όταν αντιμετωπίζουμε τέτοια προβλήματα, ώστε να μην χρειαστεί να καταφύγουμε σε cursors. Χρησιμοποιείται στο FROM clause και μας επιτρέπει να εφαρμόσουμε ένα table expression για κάθε εγγραφή του εξωτερικού πίνακα, όπου table expression μπορεί να είναι ένα view, ένας πίνακας ή ένα table function.

Ας δούμε ένα παράδειγμα:

Θέλουμε ένα report όπου για κάθε κατηγορία προϊόντων θα εμφανίζονται τα 3 πιο ακριβά προϊόντα.

Αρχικά, ορίζουμε το table function το οποίο έχει ως παράμετρο το CategoryID και βάσει αυτού φέρνει με TOP(3) τα τρία ακριβότερα προϊόντα.

CREATE FUNCTION MostExpensiveProducts(@CatID int)  
RETURNS TABLE AS 
RETURN 
  SELECT TOP (3) ProductID, ProductName, UnitPrice 
  FROM dbo.Products 
  WHERE CategoryID = @CatID 
  ORDER BY UnitPrice DESC 

Κατόπιν είμαστε έτοιμοι να γράψουμε το query μας:

SELECT CategoryName, MEP.ProductName, MEP.UnitPrice 
FROM Categories  
CROSS APPLY MostExpensiveProducts(CategoryID) AS MEP 

Και το output για μερικούς-μερικούς που δεν έχουν εγκαταστήσει SQL Server 2005 ακόμη!

CategoryName    ProductName                              UnitPrice

————— —————————————- ———————

Beverages       Côte de Blaye                            263.50

Beverages       Ipoh Coffee                              46.00

Beverages       Chang                                    19.00

Condiments      Vegie-spread                             43.90

Condiments      Northwoods Cranberry Sauce               40.00

Condiments      Sirop d’érable                           28.50

Confections     Sir Rodney’s Marmalade                   81.00

Confections     Tarte au sucre                           49.30

Confections     Schoggi Schokolade                       43.90

Dairy Products  Raclette Courdavault                     55.00

Dairy Products  Queso Manchego La Pastora                38.00

Dairy Products  Gudbrandsdalsost                         36.00

Grains/Cereals  Gnocchi di nonna Alice                   38.00

Grains/Cereals  Wimmers gute Semmelknödel                33.25

Grains/Cereals  Gustaf’s Knäckebröd                      21.00

Meat/Poultry    Thüringer Rostbratwurst                  123.79

Meat/Poultry    Mishi Kobe Niku                          97.00

Meat/Poultry    Alice Mutton                             39.00

Produce         Manjimup Dried Apples                    53.00

Produce         Rössle Sauerkraut                        45.60

Produce         Uncle Bob’s Organic Dried Pears          30.00

Seafood         Carnarvon Tigers                         62.50

Seafood         Ikura                                    31.00

Seafood         Gravad lax                               26.00

Το σημαντικό εδώ είναι ότι έχουμε τη δυνατότητα να περνάμε τα πεδία από την εγγραφή του αριστερού πίνακα προς τον δεξιό πίνακα, δηλαδή για κάθε εγγραφή του πίνακα Categories περνάμε το CategoryID ως παράμετρο στο table-function. Επίσης, αν υποθέσουμε ότι είχαμε κάποια κατηγορία προϊόντων, χωρίς όμως προϊόντα, θα μπορούσαμε να χρησιμοποιήσουμε το OUTER APPLY ώστε να εμφανιστεί και αυτή η κατηγορία, με nulls όμως στα πεδία ProductName και UnitPrice.

Advertisements


Σχολιάστε

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s