How do you select an exact date in SQL? - sql

select o.customerid, c.customername, o.orderdate
from orders as o, customers as c
where o.orderdate='1997-08-26';
Using the sample northwind db, I can't quite figure out what is wrong? I have used the format of the date that is used in the sample table.
I am trying to extract the ID and name of anyone that placed an order on the 26th.

You need to JOIN the orders and customers tables to each other:
select o.customerid, c.customername, o.orderdate
from orders as o, customers as c
where o.orderdate='19970826'
AND o.customerid = c.customerid
Using explicit syntax:
SELECT o.customerid,
c.customername,
o.orderdate
FROM orders AS o
JOIN customers c
ON c.customerid = o.customerid
WHERE o.orderdate = '19970826'
You should also read about explicit vs. implicit JOIN syntax.

This method will allow the query to use an index on orderdate:
SELECT o.customerid,
c.customername,
o.orderdate
FROM orders AS o
JOIN customers c
ON c.customerid = o.customerid
WHERE o.orderdate >= '1997-08-26'
AND o.orderdate < '1997-08-27'

try this
select o.customerid, c.customername, o.orderdate
from orders as o inner join customers as c
on o.customerid=c.customerid
where CONVERT(VARCHAR(10), o.orderdate, 120)='1997-08-26';
Updated with Join

Related

SQL - List all customers that we did not make a sale to in the year 1996

This is my functioning SQL query to return the customers that we sold to in 1996:
SELECT C.CustomerID, C.CompanyName
FROM Customers C, Orders O
WHERE C.CustomerID = O.CustomerID AND YEAR(O.OrderDate) = 1996
GROUP BY C.CustomerID, C.CompanyName
ORDER BY C.CustomerID
Now I'm trying to show the opposite; return all customers that we did not sell to in 1996 (even if we did sell to them in other years). This is what I have, however it returns both the customers we didn't sell to in 1996 but also the ones we did:
SELECT C.CustomerID, C.CompanyName FROM Orders O JOIN Customers C
ON O.CustomerID = C.CustomerID
WHERE YEAR(O.OrderDate) != 1996
GROUP BY C.CustomerID, C.CompanyName
ORDER BY C.CustomerID
You can use a correlated subquery that gets the orders from 1996 of a customer with NOT EXISTS.
SELECT c.customerid,
c.companyname
FROM customers c
WHERE NOT EXISTS (SELECT *
FROM orders o
WHERE o.customerid = c.customerid
AND o.orderdate >= '1996-01-01'
AND o.orderdate < '1997-01-01');
Note that you better shouldn't use year() on orderdate as this can prevent indexes form being used, so slowing down the query.
We can build on your existing query and use the left join antipattern:
SELECT C.CustomerID, C.CompanyName
FROM Customers C
LEFT JOIN Orders O
ON C.CustomerID = O.CustomerID
AND O.OrderDate >= '1996-01-01'
AND O.OrderDate < '1997-01-01'
WHERE O.CustomerID IS NULL
ORDER BY C.CustomerID
This phrases as : try to join each customers with the orders they have placed in 1996, and filter on those without any order.
Side note:
always use explicit, standard join (with the ON keyword); old-school, implicit joins should be avoided (no comma in the FROM clause)
as also commented by sticky bit (whose answer is valid and I upvoted it), using date comparison is better form performance than relying on date functions
try this
SELECT C.CustomerID, C.CompanyName FROM Customers C
WHERE
not exists(select 1 FROM Orders O where O.CustomerID = C.CustomerID and YEAR(O.OrderDate) = 1996)
ORDER BY C.CustomerID

COUNT with LEFT JOIN

Two tables named Sales.Customers and Sales.Orders.
Sales.Customers has a foreign key relationship to a column
named CustomerID in Sales.Orders.
Requirement: A query that returns all the customers. The query must also return the number of orders that each customer placed.
Query 1:
SELECT cust.cutomername,
NumberofOrders= COUNT(ord.OrderID)
FROM Sales.Customers Cust
LEFT JOIN
Sales.Orders Ord
ON Cust.CustomerID=Ord.OrderID
GROUP BY
Cust.CutomerName;
But I'm thinking of below one also,
Query2:
SELECT cust.cutomername,
NumberofOrders= COUNT(Cust.cutomerID)
FROM Sales.Customers Cust
LEFT JOIN
Sales.Orders Ord
ON Cust.CustomerID=Ord.OrderID
GROUP BY
Cust.CutomerName;
From both which one do you recommend & why?
This query:
SELECT c.customername, COUNT(o.OrderID)
FROM Sales.Customers c LEFT JOIN
Sales.Orders o
ON c.CustomerID = o.OrderID
GROUP BY c.CustomerName;
Probably returns all customers with meaningless counts -- probably 0 except for OrderIDs that happen to match CustomerIDs.
You probably intend:
SELECT c.customername, COUNT(o.OrderID)
FROM Sales.Customers c LEFT JOIN
Sales.Orders o
ON c.CustomerID = o.CustomerId
GROUP BY c.CustomerName;
In this query, the COUNT() is counting the number of matching orders. It can take the value of 0 for customers with no orders.
For this query:
SELECT c.customername, COUNT(c.OrderID)
FROM Sales.Customers c LEFT JOIN
Sales.Orders o
ON c.CustomerID = o.CustomerID
GROUP BY c.CustomerName;
The COUNT() is returning the number of rows. Every customer has at least one row, so the value would never be 0. Normally, you want the previous query.
Maybe this is your solution:
select c.Customername,
NumberOfOrders = (select count(o.OrderID) from Sales.Orders o where o.CustomerID = c.CustomerID)
from Sales.Customers c
order by c.Customername

How would I limit the results to a certain number and more?

So I'm trying to limit the results only to those that placed 2 or more orders but I'm not sure what I did or what I need to do in order to get that result.
Here is what I've gotten so far:
SELECT C.CustomerID,
C.CompanyName,
OrdersPlaced = COUNT( O.OrderID),
TotalPrice = SUM( D.Quantity * D.UnitPrice)
FROM Customers AS C
INNER JOIN Orders AS O ON C.CustomerID = O.CustomerID
INNER JOIN [Order Details] AS D ON O.OrderID = D.OrderID
WHERE O.OrderID >= 3
GROUP BY
O.OrderID,
C.CustomerID,
C.CompanyName;
Just add:
having count(distinct o.orderid) >= 2
I think the query you need is:
SELECT C.CustomerID, C.CompanyName,
OrdersPlaced = COUNT( O.OrderID),
TotalPrice = SUM( D.Quantity * D.UnitPrice)
FROM Customers C INNER JOIN
Orders O
ON C.CustomerID = O.CustomerID INNER JOIN
[Order Details] D
ON O.OrderID = D.OrderID
WHERE O.OrderID >= 3
GROUP BY C.CustomerID, C.CompanyName;
You also need to remove the OrderId from the GROUP BY.

How do I make the GROUP BY clause in this query run?

Write a SELECT statement that returns three columns:
EmailAddress, OrderID, and the order total for each customer.
To do this, you can group the result set by the EmailAddress and OrderID columns.
In addition, you must calculate the order total from the columns in the OrderItems table.
SELECT c.EmailAddress, oi.OrderID, (oi.ItemPrice * oi.Quantity) -
oi.DiscountAmount
FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID
JOIN OrderItems oi ON o.OrderID = oi.OrderID
GROUP BY c.EmailAddress, oi.OrderID
You are looking for GROUP BY and SUM():
SELECT c.EmailAddress, oi.OrderID,
SUM(oi.ItemPrice * oi.Quantity - oi.DiscountAmount)
FROM Customers c JOIN
Orders o
ON c.CustomerID = o.CustomerID JOIN
OrderItems oi
ON o.OrderID = oi.OrderID
GROUP BY c.EmailAddress, oi.OrderID;
Column must appear in the GROUP BY clause or be used in an aggregate function. Your column
(oi.ItemPrice * oi.Quantity) - oi.DiscountAmount
does not satisfy this requirement. I assume what you want to do is
sum((oi.ItemPrice * oi.Quantity) - oi.DiscountAmount)
?

Left Join in Oracle SQL

I was going through an example of LEFT JOIN on w3schools.com.
http://www.w3schools.com/sql/sql_join_left.asp
SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;
The above query will return me all customers with No Orders as NULL Order ID+ All customers having Orders with their Order Ids
How should I modify this query so that it returns All Customers with No Orders + All Customers having Orders with Order date as '1996-09-18'
Thanks in advance.
If you want customers with no orders and those with a specific order date, then you want a WHERE clause:
SELECT c.CustomerName, o.OrderID
FROM Customers c LEFT JOIN
Orders o
ON c.CustomerID = o.CustomerID
WHERE (o.CustomerID is NULL) OR (o.OrderDate = DATE '1996-09-18)
ORDER BY c.CustomerName;
If you wanted all customers with their order on that date (if they have one), then you would move the condition to the ON clause:
SELECT c.CustomerName, o.OrderID
FROM Customers c LEFT JOIN
Orders o
ON c.CustomerID = o.CustomerID AND o.OrderDate = DATE '1996-09-18
ORDER BY c.CustomerName;
Note the difference: the first filters the customers. The second only affects what order gets shown (and NULL will often be shown).