I have four related tables "suppliers", "products", "orderdetails", "orders" (I think that relationship should be made)
-"suppliers" has these columns
SUPPLIERID, COMPANYNAME, CONTACTNAME,
CONTACTTITLE, ADDRESS, CITY, REGION,
POSTALCODE, COUNTRY, PHONE, FAX, HOMEPAGE
-"products" has these columns
PRODUCTID, PRODUCTNAME, SUPPLIERID,
CATEGORYID, QUANTITYPERUNIT, UNITPRICE,
UNITSINSTOCK, UNITSONORDER, REORDERLEVEL, DISCONTINUED
-"orderdetails" has these columns
ORDERID, PRODUCTID, UNITPRICE,
QUANTITY, DISCOUNT
-"orders" has these columns
ORDERID, CUSTOMERID, EMPLOYEEID,
TERRITORYID, ORDERDATE, REQUIREDDATE,
SHIPPEDDATE, SHIPVIA, FREIGHT, SHIPNAME,
SHIPADDRESS, SHIPCITY, SHIPREGION, SHIPPOSTALCODE,
SHIPCOUNTRY
I need the names of the suppliers that served products the first two days of June 1997
I tried to do this but it doesn't work:
SELECT DISTINCT companyname FROM suppliers
JOIN products ON suppliers.supplierid=products.supplierid
JOIN orderdetails ON products.productid=orderdetails.productid
JOIN orders ON orderdetails.orderid=orders.orderid
where orderdate between TO_DATE('01/06/97', 'DD/MM/YY')
AND TO_DATE('02/06/97', 'DD/MM/YY');
CodePudding user response:
You have two problems:
- You are using the format model
YYwhich assumes that the date is in the current century so you are looking for dates in2097and not1997. To fix it you can use theRRformat model, a 4-digit year or use a date literalDATE '1997-06-01'. - In Oracle, a
DATEis a binary data type that ALWAYS contains 7-bytes representing century, year-of-century, month, day, hour, minute and second; so it will always have a time component. You are searching from??97-06-01 00:00:00to??97-06-02 00:00:00and you will miss any data on the second day that does not have a midnight time component. You can search on the entire range or you canTRUNCate the time component to midnight.
To fix it you can use:
SELECT DISTINCT companyname
FROM suppliers
JOIN products ON suppliers.supplierid=products.supplierid
JOIN orderdetails ON products.productid=orderdetails.productid
JOIN orders ON orderdetails.orderid=orders.orderid
WHERE orderdate >= DATE '1997-06-01'
AND orderdate < DATE '1997-06-03';
or:
SELECT DISTINCT companyname
FROM suppliers
JOIN products ON suppliers.supplierid=products.supplierid
JOIN orderdetails ON products.productid=orderdetails.productid
JOIN orders ON orderdetails.orderid=orders.orderid
WHERE TRUNC(orderdate) BETWEEN TO_DATE('01/06/97', 'DD/MM/RR')
AND TO_DATE('02/06/97', 'DD/MM/RR');
Note: filtering on a date range allows Oracle to use an index on the orderdate column; if you use a function, such as TRUNC then Oracle will not use an index on the column and would require a separate function-based index.
CodePudding user response:
Use the following code it may help you.
Modified answer
I apologize for the confusion. In Oracle, you can use the TRUNC function to truncate the time part of the 'orderdate' field, like so:
SELECT DISTINCT companyname FROM suppliers
JOIN products ON suppliers.supplierid=products.supplierid
JOIN orderdetails ON products.productid=orderdetails.productid
JOIN orders ON orderdetails.orderid=orders.orderid
WHERE TRUNC(orderdate) BETWEEN TO_DATE('1997-06-01','YYYY-MM-DD') AND TO_DATE('1997-06-02','YYYY-MM-DD')
Or the following
SELECT DISTINCT companyname FROM suppliers
JOIN products ON suppliers.supplierid=products.supplierid
JOIN orderdetails ON products.productid=orderdetails.productid
JOIN orders ON orderdetails.orderid=orders.orderid
WHERE orderdate >= TO_DATE('1997-06-01','YYYY-MM-DD') AND orderdate < TO_DATE('1997-06-03','YYYY-MM-DD')
In this way you truncate the date to the day level and compare the date part of the field.
