490 likes | 633 Views
SQL (Structured Query Language). ความเป็นมาของภาษาSQL.
E N D
ความเป็นมาของภาษาSQL ในการสอบถามข้อมูลจากฐานข้อมูลนั้น คำถามของผู้ใช้ เรียกว่า “Query” และภาษาที่ใช้ในการสอบถามข้อมูลเรียกว่า “Query Language” ซึ่งในปัจจุบันมีอยู่หลายภาษาด้วยกัน โดยภาษา SQL พัฒนาโดยบริษัท IBM เป็นที่รู้จักและใช้กันอย่างแพร่หลาย จึงถือเป็นมาตรฐานที่ใช้ใน RDBMS หลายตัวที่ใช้อยู่ในปัจจุบัน
ประเภทของคำสั่งในภาษา SQL • DDL (Data Definition Language) เป็นชุดคำสั่งที่ใช้ในการนิยาม กำหนด หรือการสร้างข้อมูลบนฐานข้อมูล ได้แก่ คำสั่ง CREATE TABLE, CREATE VIEW • DML (Data Manipulation Language) เป็นชุดคำสั่งที่ใช้ในการประมวลผลหรือจัดการกับข้อมูลในฐานข้อมูล ได้แก่ คำสั่ง SELECT, INSERT , UPDATE เป็นต้น • DCL (Data Control Language) เป็นคำสั่งที่ใช้ในการควบคุมสิทธิ์ของผู้ใช้ในการใช้ข้อมูล รวมทั้งส่วนที่ใช้ควบคุมการใช้ฐานข้อมูลจากผู้ใช้หลายๆคนพร้อมกัน
รายละเอียดข้อมูล (Data Dictionary)
รายละเอียดข้อมูล (Data Dictionary)
การสร้างตาราง(Create Table) CREATE TABLE <Table_name> (<column_name_1> <data_type> [NOT NULL] [UNIQUE], (<column_name_2> <data_type> [NOT NULL] [UNIQUE], … … … … … … [PRIMARY KEY (column_name,)] [FOREIGN KEY (column_name) REFERENCES table_name]); • การสร้างตารางด้วย SQL สามารถทำได้ด้วยคำสั่ง CREATE TABLE ซึ่งกำหนดลักษณะของข้อมูลเป็นคอลัมน์ โดยมีรูปแบบดังนี้ รูปแบบ >>
การเปลี่ยนโครงสร้างของตาราง (Alter Table) เช่น >> เพิ่มคอลัมน์ที่เป็นรหัสแผนก(IDdepartment) ในตาราง employee เพื่อบอกว่าพนักงานสังกัดอยู่แผนกใด ในการทำงานจริง อาจมีการเปลี่ยนแปลงโครงสร้างข้อมูลของตารางนั้นๆ เนื่องจากการออกแบบที่อาจผิดพลาด หรืออาจเปลี่ยนความต้องการ ในการแก้ไขโครงสร้างของตารางนั้นทำได้ด้วยคำสั่ง ALTER TABLE โดยมีรูปแบบดังนี้ รูปแบบ >> ALTER TABLE <Table_name> ADD <colum_name> <data_type> ; SQL >> ALTER TABLE employeeADD IDdepartment char(6) ;
การเปลี่ยนโครงสร้างของตาราง (Alter Table) เช่น >> ลบคอลัมน์ที่เป็นรหัสแผนก(IDdepartment) ในตาราง employee หากต้องการลบคอลัมน์ก็สามารถทำได้เช่นกันด้วยคำสั่งต่อไปนี้ รูปแบบ >> ALTER TABLE <Table_name> DROP <colum_name> ; SQL >> ALTER TABLE employeeDROP Iddepartment ;
การแก้ไขคอลัมน์ในตาราง (MODIFY) รูปแบบ >> ALTER TABLE <Table_name> MODIFY <colum_name> <data_type> ; เช่น >> เปลี่ยนขนาดของข้อมูลในคอลัมน์ Iddeparment ในตาราง employee จากขนาด 6 ตัวอักษร เป็นขนาด 5 ตัวอักษร SQL >> ALTER TABLE employeeMODIFY (IDdepartment char(5)) ;
การลบตารางออกจากฐานข้อมูล (Drop Table) DROP TABLE Order รูปแบบ >> DROP TABLE <Table_name>; ต้องการลบเทเบิล ORDER ออกจากฐานข้อมูล เช่น >> DROP TABLE ORDER; SQL>>
การเพิ่มข้อมูลแต่ละแถว (INSERT) รูปแบบ >> INSERT INTO <Table_name> VALUES ([<value 1>, <value 2>,… ) ; ป้อนข้อมูลของลูกค้าใหม่ ซึ่งมีรหัส 101 ชื่อ Supaporn อาศัยอยู่ Pattani เบอร์โทรศัพท์ 073658758 มีวงเงิน 150,000 บ. และยอดเงินคงเหลือ100,000 บ. เช่น>> INSERT INTO customer VALUES (‘101’,‘Supaporn’, ‘Pattani’,‘073658758’, 150000 ,100000 ) ; SQL>>
การเพิ่มข้อมูลแต่ละแถว (INSERT) (ต่อ) ในกรณีที่อาจการเพิ่มข้อมูลเฉพาะบางคอลัมน์ สามารถเขียนคำสั่งได้ดังนี้ รูปแบบ >> INSERT INTO <Table_name><(list of columnname)> VALUES <( list of matching value)> ; เช่น>> ป้อนข้อมูลของลูกค้าใหม่ ซึ่งมีรหัส 150 ชื่อ Walaiporn INSERT INTO customer (IDcustomer , C_name) VALUES (‘150’,‘Walaiporn’) ; SQL>>
การเพิ่มข้อมูลโดยใช้ข้อมูลจากตารางอื่นการเพิ่มข้อมูลโดยใช้ข้อมูลจากตารางอื่น ในกรณีที่อาจการเพิ่มข้อมูลเฉพาะบางคอลัมน์ สามารถเขียนคำสั่งได้ดังนี้ 1. สร้างตาราง CustomerInBangkok CREATE TABLE CustomerInBangkok (IDBangkok char(6) NOT NULL UNIQUE, B_name varchar(40) NOT NULL, B_telephone char(10) ); ต้องการสร้างตารางใหม่ ชื่อ CustomerInBangkok ซึ่งประกอบด้วยคอลัมน์ รหัส, ชื่อ และเบอร์โทรศัพท์ของลูกค้า โดยข้อมูลในตารางจะเลือกจากตาราง customer เฉพาะลูกค้าที่อาศัยอยู่ใน ‘Bangkok’ เท่านั้น เช่น>> SQL>> 2. เพิ่มข้อมูลลงในตาราง CustomerInBangkok INSERT INTO CustomerInBangkok SELECT IDcustomer , C_name,C_telephone FROM Customer WHERE address =‘Bangkok’ ;
การแก้ไขข้อมูล (Update) UPDATE employee SET E_salary= 15000 WHERE E_name=‘Piyanuch’ ; ในกรณีที่เพิ่มข้อมูลในตารางแล้ว และต้องการแก้ไขข้อมูลที่มีอยู่สามารถเขียนคำสั่งได้ดังนี้ UPDATE <Table_name> SET <columnname> = new_value WHERE <condition>; รูปแบบ>> เช่น>> ต้องการปรับเงินเดือนพนักงานชื่อ Piyanuch จากเดิม 14,400 บาท เป็น 15,000 SQL>>
การแก้ไขข้อมูล (Update) UPDATE customer SET C_credit = C_credit + 50000 WHERE C_address =‘Bangkok’ ; หากต้องการแก้ไขข้อมูลที่มีอยู่ ครั้งละหลายแถวสามารถเขียนคำสั่งได้ดังนี้ เช่น>> ต้องการเพิ่มวงเงินให้แก่ลูกค้าที่อาศัยอยู่ใน Bangkok อีกคนละ 50,000 บาท SQL>>
การลบข้อมูล (Delete) DELETE <Table_name> WHERE <condition>; รูปแบบ>> เช่น>> ในกรณีที่พนักงานชื่อ ‘Walai’ ลาออกจากบริษัท DELETEFROM employee WHERE E_name = ‘Walai’ ; SQL >>
การสอบถามข้อมูล (SELECT) รูปแบบ>> SELECT column_name, list of column_name, or * FROM table_name ,or list of table_name; เช่น>> ต้องการสอบถามข้อมูลทั้งหมดของลูกค้า SELECT Idcustomer ,C_name,C_address, C_telephone,C_Credit, C_currlim,C_currbal FROM Customer ; SQL1>> SQL2 >> SELECT * FROM Customer ; *** ในกรณีที่ต้องการเรียงลำดับการแสดงข้อมูล สามารถระบุชื่อคอลัมน์เรียงตามลำดับที่ต้องการโดยไม่จำเป็นต้องเรียงตามลำดับที่สร้างในตาราง
การเปลี่ยนหัวคอลัมน์เป็นข้อความอื่น (SELECT…AS) รูปแบบ>> SELECT column_name AS “NEW HEADING”; เช่น>> แสดงชื่อและยอดคงเหลือของลูกค้าทุกคนโดยให้หัวคอลัมน์ ชื่อ แสดงเป็น Customer_name และ ยอดเงิน แสดงเป็น Current Balance SELECT C_name AS “Customer_name”, C_currbal AS “Current Balance” FROM customer; SQL >> Customer_name Current Balance------------------- --------------------- Sopha 1000000 Silee 2000000 … … ผลลัพธ์>>
แสดงข้อมูลที่ไม่ซ้ำกันด้วย DISTINCT รูปแบบ>> SELECT DISTINCT Columnname FROM Table_name; เช่น>> ให้แสดงข้อมูลที่อยู่ลูกค้าของบริษัทว่าอยู่ที่ใดบ้าง SELECT DISTINCT address FROM customer ; SQL >>
จัดเรียงข้อมูลด้วย ORDER BY รูปแบบ>> ORDER BY column_name [DESC] ; เรียงจากมากไปน้อย ORDER BY column_name ; เรียงจากน้อยไปมาก เช่น>> ต้องการทราบรหัสและชื่อของลูกค้าทั้งหมด โดยแสดงผลแบบเรียงตามลำดับชื่อลูกค้าจากน้อยไปหามาก และ มากไปน้อย SELECT IDCustomer , C_name FROM customer ORDER BY C_name; SQL น้อยไปหามาก SELECT IDCustomer , C_name FROM customer ORDER BY C_name DESC; SQL มากไปหาน้อย
จัดเรียงข้อมูล ต้องการสอบถามชื่อ ที่อยู่ และวงเงินของลูกค้า โดยเริ่มแสดงข้อมูลจากกลุ่มลูกค้าที่มีที่อยู่เดียวกันจากน้อยไปหามาก และในแต่ละกลุ่มหรือจังหวัดก็เรียงตามชื่อลูกค้าจากน้อยไปหามาก เช่น >> SELECT C_address , C_name, C_creditlim FROM customer ORDER BY address, C_name; SQL >> address C_name C_Creditlim --------- ---------- --------------- Ayuthaya Worachat 5000000 Bangkok Anan 1000000 Bangkok Silee 6000000 ผลลัพธ์ >>
การจัดกลุ่มข้อมูล (SELECT… GROUP BY) SELECT column_name FROM <table name> GROP BY <column name> ; รูปแบบ>> เช่น>> ต้องการทราบค่าเฉลี่ยของวงเงินของลูกค้าแต่ละกลุ่ม โดยแบ่งกลุ่มตามที่อยู่ SELECT address, AVG(credit_lim) FROM customer GROUP BY address; SQL >>
เลือกกลุ่มข้อมูลด้วย HAVING และ “WHERE ต้องการทราบค่าเฉลี่ยของวงเงินของลูกค้าแต่ละกลุ่ม โดยแบ่งกลุ่มตามที่อยู่ที่มีวงเงินเฉลี่ยตั้งแต่ 300,000 ขึ้นไป SELECT column_name FROM <table name> GROP BY <column name> HAVING <condition> ; เช่น>> รูปแบบ>> SELECT address, AVG(credit_lim) FROM customer GROUP BY address HAVING AVG(credit_lim)>=300000 ; SQL >> address AVG(credit_lim) Ayuthaya 800000 Bangkok 533333.33 Rayong 300000 ผลลัพธ์>>
เลือกกลุ่มข้อมูลด้วย HAVING และ “WHERE SELECT column_name FROM <table name> WHERE <condition> GROP BY <column name> HAVING <condition> ; ต้องการทราบค่าเฉลี่ยของวงเงินของลูกค้าที่อยู่ในกรุงเทพและระยองโดยแบ่งกลุ่มตาม ที่อยู่ที่มีวงเงินเฉลี่ยตั้งแต่ 300,000 ขึ้นไป เช่น>> รูปแบบ>> SQL >> ผลลัพธ์>> SELECT address, AVG(credit_lim) FROM customer WHERE address IN (‘Bangkok’ , ‘Rayong’) GROUP BY address HAVING AVG(credit_lim)>=300000 ; address AVG(credit_lim) Bangkok 533333.33 Rayong 300000
การสอบถามข้อมูลแบบมีเงื่อนไขการสอบถามข้อมูลแบบมีเงื่อนไข SELECT column_name FROM table_name WHERE condition ; รูปแบบ>> เช่น>> ต้องการข้อมูลทั้งหมดของลูกค้าเฉพาะที่อาศัยอยู่ในBangkok SQL >> SELECT * FROM customer WHERE address = ‘Bangkok’ ;
ตัวดำเนินการเชิงเปรียบเทียบ(Comparison Operators)
ระบุหลายเงื่อนไขโดยใช้ OR โจทย์>> สอบถามข้อมูลของลูกค้าที่อยู่ Bangkok และมีวงเงินมากกว่า 500,000 บาท SELECT * FROM customer WHERE (C_address = ‘Bangkok’) AND (C_creditlim> 500000) ; SQL >> โจทย์>> สอบถามข้อมูลของลูกค้าที่อยู่ Bangkok หรือมีวงเงินมากกว่า 500,000 บาท SELECT * FROM customer WHERE (C_address = ‘Bangkok’) OR (C_creditlim> 500000) ; SQL >>
ระบุหลายเงื่อนไขโดยใช้ IN โจทย์>> สอบถามข้อมูลของลูกค้าที่อยู่ Bangkok, Rayong หรือ Ayuthaya SELECT * FROM customer WHERE (C_address = ‘Bangkok’) OR (C_address = ‘Rayong’) OR (C_address = ‘Ayuthaya’) ; SQL 1 >> SELECT * FROM customer WHERE address IN (‘Bangkok’, ‘Rayong’ , ‘Ayuthaya’) SQL 2 >>
ระบุหลายเงื่อนไขโดยใช้ NOT เช่น>> สอบถามข้อมูลของลูกค้าที่ไม่อยู่ในBangkok SELECT * FROM customer WHERE C_address != ‘Bangkok’ ; SQL1 >> SELECT * FROM customer WHERENOT C_address = ‘Bangkok’; SQL2 >>
เลือกข้อมูลที่อยู่ในช่วงที่ต้องการด้วย BETWEEN…AND SELECT column_name FROM table_name WHERE column_name BETWEEN values1 AND values2 ; รูปแบบ >> *** สำหรับเลือกแสดงข้อมูลที่อยู่ระหว่างค่าที่กำหนด(values1) และ values2*** SELECT column_name FROM table_name WHERE column_name NOT BETWEEN values1 AND values2 ; รูปแบบ >> *** สำหรับเลือกแสดงข้อมูลที่มีค่าไม่อยู่ระหว่างค่าที่กำหนด***
เลือกข้อมูลที่อยู่ในช่วงที่ต้องการด้วย BETWEEN…AND เช่น>> แสดงชื่อของพนักงานที่มีเงินเดือนอยู่ระหว่าง 3,500 และ 5,000 บาท SELECT e_name FROM employee WHERE (salary >= 3500) AND (salary <= 5000) ; SQL1 >> SELECT e_name FROM employee WHERE salary BETWEEN 3500 AND 5000 ; SQL2 >>
เลือกข้อมูลที่ตรงกับความต้องการด้วย LIKE คำสั่ง SQL สามารถกำหนดเงื่อนไขเพื่อเลือกข้อมูลโดยใช้คำว่า “LIKE” และ ‘_’ โดยมีรายละเอียดดังนี้
เลือกข้อมูลที่ตรงกับความต้องการด้วย LIKE เช่น>> แสดงชื่อของลูกค้าที่ขึ้นต้นด้วย ‘So’ C_name ------------ Sopha SomchaiSomsak ผลลัพธ์>> SELECT C_name FROM customer WHERE c_name like ‘So%’ ; SQL1 >> เช่น>> แสดงชื่อของลูกค้าที่ขึ้นต้นด้วย ‘Si’ และตามด้วยอักษรได้ก็ได้ 3 ตัว C_name ------------ Silee SELECT C_name FROM customer WHERE c_name like ‘Si_ _ _’ ; ผลลัพธ์>> SQL1 >>
ฟังก์ชั่นสำหรับการคำนวณทางคณิตศาสตร์ฟังก์ชั่นสำหรับการคำนวณทางคณิตศาสตร์
ฟังก์ชั่น ABS(m) โจทย์>> ต้องการทราบยอดเงินคงเหลือของลูกค้าแต่ละคน ว่ามีค่าต่างจากวงเงินเท่าไหร่ SELECT C_name, ABS(C_currbal – C_creditlim) AS “difference” FROM customer ; SQL1 >> ผลลัพธ์>> C_name difference ------------ ------------ Sopha 200000 Somchai 200000Somsak 100000 Amorn 47950
ฟังก์ชั่น MOD(m,n) โจทย์ >> เพื่อที่จะบรรจุหีบห่อของสินค้า กล่องละ 10 ชิ้น ให้แสดงรายการสินค้าและ เศษที่เหลือจากการบรรจุสินค้า SELECT p_name, MOD(p_onhand,10) FROM Product ; SQL1 >> p_name MOD(onhand,10) ------------ ------------ Television 0 Radio 5Table 2 Chair 0 ผลลัพธ์>>
ฟังก์ชั่น POWER(m,n) ต้องการทราบว่าถ้าขึ้นเงินเดือนให้พนักงานทุกคนมีค่าเท่ากับเงินเดือนปัจจุบันยกกำลังสองแล้ว พนักงานแต่ละคนจะมีเงินเดือนเท่าไหร่ เช่น>> SELECT e_name, POWER(e_salary,2) FROM employee; SQL1 >> e_name POWER(e_salary,2) ------------ ------------ Piya 12250000 Pinyo 24850225Wilai 6708100 … … ผลลัพธ์>>
ฟังก์ชั่น ROUND(m,n) และ TRUNC(m,n) ต้องการทราบราคาต่อหน่วยสินค้าทั้งหมด โดยแสดงเป็นทศนิยม1 ตำแหน่ง เช่น >> SQL1 >> SELECT p_name, ROUND(P_unitprice,1), TRUNC(P_unitprice,1) FROM product ; ผลลัพธ์>> p_name ROUND(P_unitprice,10) TRUNC(p_unitprice,1) ------------ ---------------- ---------------- Television 10500 10500 Radio 1595 1595Table 650 650 Chair 232.5 232.5 Ruler 1.8 1.7 Paper 62.3 62.2
ฟังก์ชั่นสำหรับหาค่าของกลุ่มข้อมูลฟังก์ชั่นสำหรับหาค่าของกลุ่มข้อมูล รูปแบบ>> SELECT Function (column_name or *) FROM table_name ;
หาค่าเฉลี่ยด้วย AVG() , MAX() โจทย์ >> ต้องการทราบค่าเฉลี่ยเงินเดือนพนักงานทุกคน AVG(salary) ------------ 4971 SELECT AVG(salary) FROM employee ; ผลลัพธ์>> SQL1 >> โจทย์ >> ต้องการทราบวงเงินสูงสุดที่ให้แก่ลูกค้ามีค่าเท่าไหร่ MAX(C_creditlim) ------------ 900000 SELECT MAX(C_creditlim) FROM Customer ; ผลลัพธ์>> SQL1 >>
การนับจำนวน COUNT, DISTINCT โจทย์ >> ต้องการทราบจำนวนลูกค้าของบริษัท count(*) ------------ 9 SELECT COUNT(*) FROM customer ; ผลลัพธ์>> SQL1 >> แสดงจำนวนรายการสั่งซื้อสินค้าทั้งหมด พร้อมระบุจำนวนรายการสินค้าทั้งหมดที่มีการสั่งซื้อ โจทย์ >> SELECT COUNT(*) AS “TOTAL” , COUNT(DISTINCT IDorder) AS “ORDER” FROM Order; SQL1 >> TOTAL ORDER ------------ ------------ 6 5 ผลลัพธ์>>
การเชื่อมตาราง (JOIN) เช่น >> ต้องการทราบว่าใบสั่งซื้อแต่ละใบมีพนักงานชื่ออะไรเป็นผู้ขาย = SQL >> SELECT DISTINCT IDorder, order.IDemployee, e_name FROM order,employee WHERE order.IDemployee= employee.IDemployee; IDorder IDemployee e_name A-001 10100 Piya A-059 1855 Sukchai ……. …… …….. ผลลัพธ์>> … … …
การใช้นิพนธ์คณิตศาสตร์ในการเชื่อมตาราง เช่น >> ต้องการทราบชื่อสินค้าและยอดเงินที่ยังไม่ได้หักลดในใบสั่งซื้อรหัส A-001 = SQL >> SELECT p_name, qty * unitprice AS “total_amount” FROM product , order WHERE IDorder= ‘A-001’ AND product.IDproduct =order. IDproduct ; ผลลัพธ์>> p_name total_amount television 3150000 …… ……..
การเชื่อมตารางแบบ Equi join เช่น >> ต้องการทราบชื่อสินค้าและยอดเงินของสินค้าในใบสั่งซื้อ ‘D-593’ โดยเรียงลำดับตามปริมาณจากมากไปหาน้อย = ผลลัพธ์>> SELECT p_name, qty FROM product , order WHERE product.IDproduct=order.Idproduct AND IDorder=‘D-593’ ORDER BY qty DESC ; SQL >> p_name qty Paper 150 Pencil 50 …… ……..
การเชื่อมตารางแบบ Self join เช่น >> พนักงานแต่ละคนต้องการทราบว่ามีพนักงานคนใดบ้างที่เงินเดือนมากกว่าตน < = SELECT E1.e_name AS “lowerpaid”, E1.salary AS “lowersalary”, E2.e_name AS “higherpaid”, E2.salary AS “highersalary” FROM employee E1, employee E2 WHERE E1.salary < E2.salary ORDER BY 1; SQL >>
การเชื่อมตารางแบบ Self join ผลลัพธ์>> lowerpaid lowersalary higherpaid highersalary Pinyo 4985 Sompat 9800 Pinya 3500 Pinyo 4985 Pinya 3500 Sukchai 3980 Pinya 3980 Sombat 9800 Sukchai 3980 Pinyo 4985 Sukchai 3980 Sombat 9800 Wilai 2590 Piya 3500 Wilai 2590 Pinyo 4985 Wilai 2590 Sombat 9800 Wilai 2590 Sukchai 3980 …… …….. …… ……..
การเชื่อมตารางแบบ Outer join โจทย์ >> แสดงรหัสและชื่อสินค้าที่ไม่มีการสั่งซื้อจากลูกค้า = SELECT p_name, P.Idproduct , IDorder FROM product P, order O WHERE P.IDproduct = O.IDproduct(+); SQL >>
การเชื่อมตารางแบบ Self join ผลลัพธ์>> IDproduct p_name IDorder 10515 Television A-001 10515 Television C-523 20001 Radio B-191 20002 Table A-059 21011 Chair 35155 Pencil D-593 36710 Ruler 39001 Paper D-593 …… …….. …….. แถวที่ไม่มีข้อมูลในorder
ชนิดข้อมูลของ sql มีหลายประเภท ได้แก่ character ใช้จัดเก็บตัวอักษรที่แน่นอน ( ใช้ 1 byte ต่อ 1 ตัวอักษร ), character varying ใช้จัดเก็บตัวอักษร( ใช้ 1 byte ต่อ 1 ตัวอักษร ), national character ใช้จัดเก็บตัวอักษรที่แน่นอน ( ใช้ 2 bytes ต่อ 1 ตัวอักษร ),national character varying ใช้จัดเก็บตัวอักษร ( ใช้ 2 bytes ต่อ 1 ตัวอักษร ), integer ใช้จัดเก็บเลขจำนวนเต็ม ( ระหว่าง -2,147,483,648 ถึง 2,147,483,647 ),smalling ใช้จัดเก็บเลขจำนวนเต็ม ( ระหว่าง -32,768 ถึง 32767 ),real ใช้จัดเก็บเลขจำนวนจริง ( ระหว่าง -3.40E + 38 ถึง 3.40E + 38 ),decimal ใช้จัดเก็บเลขจำนวนจริง ,date ใช้จัดเก็บค่าวันที่,time ใช้จัดเก็บค่าเวลา