sqlschool.gr logo

articles

Articles of SQLschool.gr Team

Πώς εκτελείται λογικά ένα sql query;

Antonios Chatzipavlis
Wednesday 26 August 2009

Τόσα χρόνια στον χώρο της πληροφορικής έχω μάθει να προσπαθώ να καταλάβω τι γίνεται πίσω από την σκηνή με αυτό που ασχολούμαι. Ο SQL Server είναι ένα από αυτά, και στο οποίο έχω αφιερώσει αρκετές τρίχες της κεφαλής μου. Σήμερα θα σας πάρω λίγο από τον πολύτιμο χρόνο σας για να σας μεταφέρω μια γνώση που θα σας φανεί αρκετά χρήσιμη.

Όλοι λίγο ή πολύ έχετε γράψει ένα sql query. Άλλες φορές αυτό λειτούργησε άψογα άλλες φορές όχι. Το μυστικό για να γράψεις ένα καλό sql query είναι να έχεις κατανοήσει πως αυτό λογικά εκτελείται, ιδιαίτερα στην μηχανή που χρησιμοποιείς, στην δικιά μας περίπτωση ο SQL Server.

Ένα sql query περιέχει κάποιες εκφράσεις μέσα του, εδώ θα ασχοληθούμε με τι βασικές, Έτσι ένα sql query είναι της μορφής αυτής. Στους αριθμούς μέσα στις παρενθέσεις φαίνεται η σειρά, βήμα, φάση εκτέλεσης.

Κάθε βήμα δημιουργεί έναν virtual table ο οποίος είναι το input για το επόμενο βήμα. Αυτά το virtual tables δεν είναι διαθέσιμα σε κανένα πλήν του SQL Server, εκτός του τελευταίου που είναι και αυτό που παίρνουμε σαν απάντηση. Εάν στο sql query μας δεν έχουμε κάποια έκφραση απλά αυτή αγνοείτε και πάει στο επόμενο βήμα.

 

(8) SELECT (9) DISTINCT (11) <TOP_specification> <select_list>

(1) FROM <left_table>

(3) <join_type> JOIN <right_table>

(2) ON <join_condition>

(4) WHERE <where_condition>

(5) GROUP BY <group_by_list>

(6) WITH {CUBE | ROLLUP}

(7) HAVING <having_condition>

(10) ORDER BY <order_by_list>

 

Ας δούμε τα πράγματα λίγο αναλυτικά με ένα παράδειγμα που θα δημιουργήσουμε με το παρακάτω script

SET NOCOUNT ON;

USE tempdb;

GO

IF OBJECT_ID('dbo.Orders') IS NOT NULL

DROP TABLE dbo.Orders;

GO

IF OBJECT_ID('dbo.Customers') IS NOT NULL

DROP TABLE dbo.Customers;

GO

CREATE TABLE dbo.Customers

(

customerid CHAR(5) NOT NULL PRIMARY KEY,

city VARCHAR(10) NOT NULL

);

 

INSERT INTO dbo.Customers(customerid, city) VALUES('ANTON', 'Athens');

INSERT INTO dbo.Customers(customerid, city) VALUES('NASOS', 'Athens');

INSERT INTO dbo.Customers(customerid, city) VALUES('FANIS', 'Athens');

INSERT INTO dbo.Customers(customerid, city) VALUES('CHRIS', 'Salonica');

 

CREATE TABLE dbo.Orders

(

orderid INT NOT NULL PRIMARY KEY,

customerid CHAR(5) NULL REFERENCES Customers(customerid)

);

 

INSERT INTO dbo.Orders(orderid, customerid) VALUES(1, 'NASOS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(2, 'NASOS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(3, 'FANIS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(4, 'FANIS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(5, 'FANIS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(6, 'CHRIS');

INSERT INTO dbo.Orders(orderid, customerid) VALUES(7, NULL);

Μετά από την εκτέλεση του θα έχουμε δύο πίνακες τους Customers, Orders οι οποίοι είναι related μεταξύ τους και τα δεδομένα τους θα είναι τα εξής

Customers Table Data

customerid

city

ANTON

Athens

CHRIS

Salonica

FANIS

Athens

NASOS

Athens

 

Orders Table Data

Orderid

customerid

1

NASOS

2

NASOS

3

FANIS

4

FANIS

5

FANIS

6

CHRIS

7

NULL

 

Ας πάρουμε σαν σενάριο ότι θέλουμε να βούμε τους πελάτες της Αθήνας που έχουν κάτω από τρεις παραγγελίες.

Έτσι το sql query μας θα είναι σαν αυτό.

SELECT C.customerid, COUNT(O.orderid) AS numorders

FROM dbo.Customers AS C

LEFT OUTER JOIN dbo.Orders AS O

ON C.customerid = O.customerid

WHERE C.city = 'Athens'

GROUP BY C.customerid

HAVING COUNT(O.orderid) < 3

ORDER BY numorders;

Το αποτέλεσμα της εκτέλεσης του είναι το παρακάτω

Customerid

numorders

ANTON

0

NASOS

2

 

Ποιά είναι όμως η λογική του εκτέλεση; Ας δούμε λοιπόν τα βήματα της εκτέλεσης.

Βήμα 1ο - Cross Join

FROM dbo.Customers AS C ... JOIN dbo.Orders AS O

 

Εδώ φτιάχνει το καρτεσιανό γινόμενο των δύο πινάκων και το βάζει στο 1ο virtual table (VT1). Το περιεχόμενο του πίνακα αυτού είναι 28 γραμμές ( 4x7).

Customerid

City

Orderid

customerid

ANTON

Athens

1

NASOS

ANTON

Athens

2

NASOS

ANTON

Athens

3

FANIS

ANTON

Athens

4

FANIS

ANTON

Athens

5

FANIS

ANTON

Athens

6

CHRIS

ANTON

Athens

7

NULL

CHRIS

Salonica

1

NASOS

CHRIS

Salonica

2

NASOS

CHRIS

Salonica

3

FANIS

CHRIS

Salonica

4

FANIS

CHRIS

Salonica

5

FANIS

CHRIS

Salonica

6

CHRIS

CHRIS

Salonica

7

NULL

FANIS

Athens

1

NASOS

FANIS

Athens

2

NASOS

FANIS

Athens

3

FANIS

FANIS

Athens

4

FANIS

FANIS

Athens

5

FANIS

FANIS

Athens

6

CHRIS

FANIS

Athens

7

NULL

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

NASOS

Athens

3

FANIS

NASOS

Athens

4

FANIS

NASOS

Athens

5

FANIS

NASOS

Athens

6

CHRIS

NASOS

Athens

7

NULL

 

Βήμα 2ο - Apply Join condition ON Filter

ON C.customerid = O.customerid

Στο βήμα αυτό εφαρμόζεται το ON που υπάρχει στο Join και μόνο τα rows εκείνα τα οποία ικανοποιούν το βήμα πηγαίνουν στον VT2 που θα είναι το αποτέλεσμα του βήματος αυτού.

Έτσι αν πάρω τον VT1 και εφαρμόσω στο παράδειγμα μας το ON θα έχω το εξής αποτέλεσμα

Customerid

City

Orderid

customerid

ΟΝ Filter

ANTON

Athens

1

NASOS

FALSE

ANTON

Athens

2

NASOS

FALSE

ANTON

Athens

3

FANIS

FALSE

ANTON

Athens

4

FANIS

FALSE

ANTON

Athens

5

FANIS

FALSE

ANTON

Athens

6

CHRIS

FALSE

ANTON

Athens

7

NULL

UNKNOWN

CHRIS

Salonica

1

NASOS

FALSE

CHRIS

Salonica

2

NASOS

FALSE

CHRIS

Salonica

3

FANIS

FALSE

CHRIS

Salonica

4

FANIS

FALSE

CHRIS

Salonica

5

FANIS

FALSE

CHRIS

Salonica

6

CHRIS

TRUE

CHRIS

Salonica

7

NULL

UNKNOWN

FANIS

Athens

1

NASOS

FALSE

FANIS

Athens

2

NASOS

FALSE

FANIS

Athens

3

FANIS

TRUE

FANIS

Athens

4

FANIS

TRUE

FANIS

Athens

5

FANIS

TRUE

FANIS

Athens

6

CHRIS

FALSE

FANIS

Athens

7

NULL

UNKNOWN

NASOS

Athens

1

NASOS

TRUE

NASOS

Athens

2

NASOS

TRUE

NASOS

Athens

3

FANIS

FALSE

NASOS

Athens

4

FANIS

FALSE

NASOS

Athens

5

FANIS

FALSE

NASOS

Athens

6

CHRIS

FALSE

NASOS

Athens

7

NULL

UNKNOWN

 

Δηλαδή ο VT2 θα είναι τελικά ο παρακάτω

Customerid

City

Orderid

customerid

CHRIS

Salonica

6

CHRIS

FANIS

Athens

3

FANIS

FANIS

Athens

4

FANIS

FANIS

Athens

5

FANIS

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

 

Βήμα 3ο - Apply OUTER Join

FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O

Στην περίπτωση μας μόνο ένας είναι ο πελάτης από την πίνακα τον πελατών που δεν υπάρχει στον VT2 o ΑΝΤΟΝ οπότε μπαίνει και αυτό στον VT3 που είναι το αποτέλεσμα του βήματος αυτού

Customerid

City

Orderid

customerid

CHRIS

Salonica

6

CHRIS

FANIS

Athens

3

FANIS

FANIS

Athens

4

FANIS

FANIS

Athens

5

FANIS

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

ΑΝΤΟΝ

Athens

NULL

NULL

 

Βήμα 4ο - Apply WHERE filter

WHERE C.city = 'Athens'

Το αποτέλεσμα είναι ο VT4

Customerid

City

Orderid

customerid

FANIS

Athens

3

FANIS

FANIS

Athens

4

FANIS

FANIS

Athens

5

FANIS

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

ΑΝΤΟΝ

Athens

NULL

NULL

 

Βήμα 5ο - Apply Grouping

GROUP BY C.customerid

Το αποτέλεσμα είναι ο VT5

Customerid

City

Orderid

customerid

FANIS

Athens

3

FANIS

FANIS

Athens

4

FANIS

FANIS

Athens

5

FANIS

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

ΑΝΤΟΝ

Athens

NULL

NULL

 

Βήμα 6ο - Apply Cube or Rollup

Δεν έχουμε κάτι τέτοιο στο query μας οπότε πάει στο επόμενο βήμα.

Βήμα 7ο - Apply HAVING Filter

HAVING COUNT(O.orderid) < 3

Το αποτέλεσμα είναι ο VT7

Customerid

City

Orderid

customerid

NASOS

Athens

1

NASOS

NASOS

Athens

2

NASOS

ΑΝΤΟΝ

Athens

NULL

NULL

 

Βήμα 8ο - Apply SELECT List

SELECT C.customerid, COUNT(O.orderid) AS numorders

Το αποτέλεσμα είναι ο VT8

Customerid

numorders

NASOS

2

ANTON

0

Βήμα 9ο - Apply DISTINCT

Δεν έχουμε κάτι τέτοιο στο query μας οπότε πάει στο επόμενο βήμα.

Βήμα 10ο - Apply ORDER BY

SELECT C.customerid, COUNT(O.orderid) AS numorders

Το αποτέλεσμα είναι ο VT10

Customerid

numorders

ANTON

0

NASOS

2

Βήμα 11ο - Apply TOP

Δεν έχουμε κάτι τέτοιο στο query μας οπότε καταλήγουμε στο τελικό μας αποτέλεσμα.

ΥΓ. Επίτηδες παρέλειψα κάποια βήματα για να μην σας κουράσω. Αν υπάρχει απαίτηση από εσάς μέσω των σχολίων σας θα προχωρήσω βαθύτερα και σε αυτά

Antonios Chatzipavlis

Antonios Chatzipavlis

Antonios is a Data Solutions Consultant and Trainer. He has been working in IT since 1988. In his career, he has worked as senior developer, IT Manager, Solutions Architect and IT Consultant. Since 1995 he has been devoted on new technologies and software development tools, mainly by Microsoft, either by training company staff and colleagues or assisting them in design, development and implementation as a consultant or chief developer. He has focused in Databases and Data Science since 1995. He specialized in Microsoft SQL Server since version 6.0 in areas like SQL Server Internals, Database Design and Development, Business Intelligence and in 2010 he has started working with Azure Data Platform, NoSQL databases, Big Data Technologies and Machine Learning. He is an active member of many IT communities in Greece, answering colleagues' questions and writing articles in his web site. He is the owner of SQLschool.gr which is a community portal with a lot of information about Microsoft SQL Server. He has been a Microsoft Certified Trainer (MCT) since 2000. Microsoft honored him as MVP on Data Platform due to his activities in SQL Server since 2010. He holds a large number of Microsoft Certifications and Microsoft SQL Server Certifications since version 6.5.

Episode

Task Flows in Microsoft Fabric

image

More Episodes...

Tip

What's New in SQL Server 2022 - Episodes

More Tips...

Become a member

If you want to receive updates from us become a member to our community.

Connect

Explore

Learn


sqlschool.gr © 2010-2025 All rights reserved

This site uses cookies for operational and analytics purposes only. By continuing to browse this site, you agree to their use.