set path to "C:\Program Files\VS98\MSDN98\98VSa\1033\SAMPLES\VFP98\data" CLEAR ALL close data all create cursor junk1( order_id c(6), to_name c(40), prod_name c(40), first_name c(40), last_name c(40) ) USE ORDITEMS in 0 USE ORDERS IN 0 ORDER TAG Order_id USE Employee IN 0 ORDER TAG emp_id USE Products IN 0 ORDER TAG Product_id nSec=SECONDS() select orditems SET RELATION TO Order_id INTO ORDERS SET RELATION TO Product_id INTO PRODUCTS ADDITIVE SELECT Orders SET RELATION TO Emp_id INTO Employee ADDITIVE SELECT OrdItems SCAN FOR Orders.shipped_on # {} AND Products.Discontinu insert into junk1 values ( order_id, orders.to_name, products.prod_name, employee.first_name, employee.last_name ) ENDSCAN ? SECONDS() - nSec close data all USE ORDITEMS in 0 USE ORDERS IN 0 USE Employee IN 0 USE Products IN 0 nSec=SECONDS() SELECT orders.order_id, orders.to_name, products.prod_name, employee.first_name, employee.last_name; FROM Orders ; INNER JOIN Orditems ; ON orders.order_id = orditems.order_id ; INNER JOIN Products ; ON orditems.product_id = products.Product_id ; INNER JOIN Employee ; ON orders.emp_id = employee.emp_id ; WHERE shipped_on # {} AND products.Discontinu ; INTO CURSOR junk2 ? SECONDS() - nSecYou'll find that the SQL is 3.63 times faster than the xbase code! On my P2-300 notebook the average of 3 runs were 0.145 seconds for the xbase and 0.040 seconds for the SQL.