Two Tables in SQL Database - sql

beginner sql coder. I have an Access database with a customers table and orders table. The headers of the columns have a space (i.e: Shipped Date). I need to return Company Name, Contact Name, and Phone of customers who placed orders in March of 1998. Shipped Dates are formatted as 01-Mar-1998.
How do I do this? Access keeps giving me errors
SELECT Orders.*,Customers.CompanyName, Customers.ContactName, Customers.Phone
FROM Customers, Orders
(SELECT *
FROM Orders
JOIN Customers ON Orders.Order ID=Customers.Order ID)
AND Shipped Date BETWEEN #03/01/1998# AND #03/31/1998#;
GROUP BY Customers.CompanyName, Customers.ContactName, Customers.Phone;
EDIT:
New code
SELECT *
FROM Orders INNER JOIN Customers ON Orders.Customer=Customers.[Company Name]
WHERE Orders.[Shipped Date] BETWEEN #01-MAR-1998# AND #31-MAR-1998#;
The code runs, but Access prompts me to enter values for the all of the column names...Please help!

Your Query is incorrectly formed. As we should enclose the coloumns with names containing spaces in []
also tour GROUP BY was not relevant.
Now when we use JOIN we should have the query like :
SELECT * FROM Orders JOIN Customers ON Orders.[Order ID]=Customers.[Order ID]
WHERE Orders.[Shipped Date] BETWEEN #03/01/1998# AND #03/31/1998#;

Related

Countif and Sumif in Microsoft Access

I'm coming to you with a problem related to my Access database.
To keep it simple, I have two tables, Products and Customers :
Those tables come from a simple Excel file I created to keep track of sales.
In this file, the fields ItemCount and TotalBill from the Customers table are calculated fields using countif and sumif as follows :
ItemCount : =COUNTIF(Products[Customer],[#Customer])
TotalBill : =SUMIF(Products[Customer],[#Customer],Products[Price])
I've realised with despair that MS Access don't offer those functions in the calculated fields, but there must be a way to do something so basic.
The tables must be kept separated.
If someone could help me to the way I'd be most grateful
Thank you all for reading !
This looks like a join and aggregation:
select
c.customerid,
c.customer,
count(*) itemcount,
sum(p.price) totalbill
from products p
inner join customer c on c.customer = p.customer
group by c.customerid, c.customer
Note that you shouldn't be using the name of the customer to relate the two tables, but instead the customer id, which, presumably, is the primary key of the customers table.
You do not mention either you just want the result or you want to update Customers table columns with calculated value. So, if you want to display all the customer form customers table even if there is no transactions on Products table then use below query
SELECT Customers.CustomerID, Customers.Customer, P.Cnt AS ItemCount, P.Sm AS TotalBill
FROM (SELECT products.customer AS PC, Count(Products.Product) AS Cnt, Sum(Products.Price) AS Sm FROM Products GROUP BY Products.Customer) AS P
RIGHT JOIN Customers ON P.PC = Customers.Customer;
Although MS-Access discourage to store calculated value to tables [Run queries or report as need] but you can do that if you want. So, to update Customers table with values from Products table you can try below UPDATE query.
UPDATE Customers SET Customers.ItemCount =
DCount("Product","Products","Customer= '" & Customers.Customer & "'"), Customers.TotalBill =
DSum("Price","Products","Customer= '" & [Customers].[Customer] & "'");

calculates between These two columns in SQL server [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I want to add a column to the query that calculates between These two columns In the same query ....................................................................
,isnull(sum(ORDERS.Net_Amount) + 0,0) as orders
,isnull(sum (convert(float,(RECEIPTS.Amount))) + 0,0) as recepts
IN SQL SERVER
SELECT CUSTOMERS.[ID_CUSTOMER]
,[FIRST_NAME]
,[TEL]
,[EMAIL]
,isnull(sum(ORDERS.Net_Amount) + 0,0) as orders
,isnull(sum (convert(float,(RECEIPTS.Amount))) + 0,0) as recepts
,[CRIDIT_LIMIT]
,[CUSTOMER_SINCE]
,[ADRESS]
,CUSTOMERS.[state]
FROM [CUSTOMERS]
LEFT JOIN ORDERS on CUSTOMERS.ID_CUSTOMER = ORDERS.CUSTOMER_ID
LEFT JOIN RECEIPTS on CUSTOMERS.ID_CUSTOMER = RECEIPTS.ID_CUSTOMER
GROUP BY CUSTOMERS.[ID_CUSTOMER]
,[FIRST_NAME]
,[TEL]
,[EMAIL]
,[CRIDIT_LIMIT]
,[CUSTOMER_SINCE]
,[ADRESS]
,CUSTOMERS.[state]
CUSTOMERS table
SELECT [ID_CUSTOMER]
,[FIRST_NAME]
,[TEL]
,[EMAIL]
,[IMAGE_CUSTOMER]
,[CRIDIT_LIMIT]
,[CUSTOMER_SINCE]
,[ADRESS]
,[Balance]
,[state]
FROM [CUSTOMERS]
ORDERS table
SELECT [ID_ORDER]
,[DATE_ORDER]
,[CUSTOMER_ID]
,[DESCRIPTION_ORDERS]
,[SALEMAN]
,[ORDER_TOTAL]
,[Discount_Of_Total]
,[Total_After_Discount]
,[Paid_Up]
,[Net_Amount]
,[state]
FROM [ORDERS]
RECEIPTS table
SELECT [image_state]
,[ID_RECEIPT]
,[ID_CUSTOMER]
,[Date]
,[Ref]
,[Amount]
,[Memo]
,[User_Name]
,[state]
,[Payment_Method]
,[Account_ID]
FROM [RECEIPTS]
Orders and receipts are not really related to each other (the receipt doesn't refer to a specific order), so don't join the two. What you want to do instead is find the order amount and the receipt amount per customer and show them. So aggregate the two tables per customer and outer-join the results to the customer table.
select
c.id_customer,
c.first_name,
c.tel,
c.email,
coalesce(o.sum_net_amount, 0) as order_amount,
coalesce(r.sum_amount, 0) as receipt_amount,
c.cridit_limit,
c.customer_since,
c.adress,
c.balance,
c.state
from customers c
left join
(
select customer_id, sum(net_amount) as sum_net_amount
from orders
group by customer_id
) o on c.id_customer = o.customer_id
left join
(
select id_customer, sum(amount) as sum_amount
from receipts
group by id_customer
) r on c.id_customer = r.id_customer;
I see you have updated your request now asking also for the difference of the sums. Well, the operator for subtraction in SQL is - little surprising - the minus sign:
coalesce(o.sum_net_amount, 0) - coalesce(r.sum_amount, 0) as diff
Please try the following...
SELECT Customers.ID_Customer,
first_name,
tel,
email,
SUM( net_amount ) AS OrdersTotal,
COALESCE( sumAmount, 0 ) AS PaymentsTotal,
SUM( net_amount ) - COALESCE( sumAmount, 0 ) AS DifferenceInTotals,
cridit_limit,
customer_since,
adress,
balance,
state
FROM Customers
INNER JOIN Orders ON Customers.ID_Customer = Orders.Customer_ID
LEFT JOIN ( SELECT ID_Customer,
SUM( amount ) AS sumAmount
FROM Receipts
GROUP BY ID_Customer
) AS sumAmountFinder ON Customers.ID_Customer = sumAmountFinder.ID_Customer
GROUP BY Customers.ID_Customer,
first_name,
tel,
email,
cridit_limit,
customer_since,
adress,
balance,
state;
This Answer is based on the assumption that every Customer will have at least one Order, but possibly no Receipts.
This statement is essentially the one that you supplied with the following modifications...
I have changed the JOIN to Orders to an INNER JOIN, since I am assuming that each Customer will have at least one Order. The LEFT JOIN is only necessary where you wish to retain all records from the left table that do not have at least one matching record from the right table as defined by the ON clause. (Note : If you wish to retain all the records from the right table where there is no matching records from the left table, use a RIGHT JOIN).
I have replaced the JOIN to the Receipts table with a subquery that calculates the total of the amount field for each Customer in the Receipts table. A LEFT JOIN is necessary between Customers and the results of this subquery as not all Customers will have a Receipt. In such situations the LEFT JOIN will set each of the fields from the subquery in the joined dataset to NULL.
Where the SUM() function encounters only NULL values it returns NULL, not 0. So that PaymentsTotal will be set to 0 for records where the Customer has no Receipts, I have used the COALESCE() function. This function will return the first non-NULL argument it encounters. Here I have set it to return the total of amount where it encounters one, and 0 where it encounters no total amount.
I have removed all of the square brackets from your field and table names. They are only required where you have used an otherwise disallowed name, such as names with spaces (use [Full Name] instead of Full Name) or names that are also reserved by SQL-Server (if you had decided to call PaymentsTotal Sum, then you would have had to use AS [Sum]). Many programmers consider giving fields such names to be bad practice, even when it is possible with []'s, but fortunately you have not used any otherwise names.
I have removed the table names from your SUM() calculations. Since only one table has a field called net_amount, then it will be a unique field name in the joined dataset, and you will be able to refer to them without specifying the name of the source table as well. Specifying the source table is still necessary in the case of Customers.ID_Customer as the joined dataset will have more than one field called ID_Customer. Also, you will need to specify the source tables names when creating the joined dataset using the JOIN's.
I have also taken the liberty of changing your capitalisation scheme. Having just about everything in constant upper-case is monotonous to the eye. Using different casing for SQL terms, table names and field names makes recognising each type of statement part much easier, and thus makes debugging code much easier.
Finally, and relatively trivially, cridit is actually spelt credit and adress is actually spelt address.
If you have any questions or comments, then please feel free to post a Comment accordingly.

SQL Query that returns only records with multiple rows

I have a database with two tables: Customers and Services.
The Customer table has account information and the Services table has individual records of every service my company has performed.
The Services table is linked to the Customer table with an ID column where Customers.ID = Services.CustomerID.
I am trying to perform a query which will return the customer name and account number for only those customers where more than one service has been performed within a specified date range. For example, show me all customers where I've performed work more than twice in 2015.
How do I write this type of query so that only those with multiple service visits are returned? I can do this using cursors, counting results, etc. but it seems there must be a more efficient way.
Just use a JOIN and a GROUP BY like so:
SELECT Customers.ID
FROM Customers
JOIN Services ON Customer.ID=Services.CustomerID
--WHERE your Services date check here
GROUP BY Customers.ID -- you can add more columns from the customers table here and in the select as needed
HAVING SUM(1)>1
You can add a WHERE clause to filter the Services' date range (just before the GROUP BY).
Select Id from Customers C where count (select * from Services S where C.id = S.CustomersId ) > 1
SELECT Customers.CustomerID
,Customers.Name
,Customers.AcoountNumber
FROM Customers
JOIN
(
select Services.CustomerID, Services.CustomerID as totalServices
from Services
where Services.date BETWEEN #FROM_DATE AND #TO_DATE
group by Services.CustomerID
having count(Services.CustomerID) >1
) AS CustomersMoreThan1 on Customers.CustomerID=CustomersMoreThan1.CustomerID
This query allows you to add more columns from your Customer table without having to modify your GROUP BY.

Sql Statement trying to understand join statements

My code is pasted here for the Sql tables and information: http://pastebin.com/GsKp4z30
what I am trying to do is:
SuperClean would like to offer a special to their customers that use coupons. Retrieve the names and
addresses for the customers using coupons on any order from September 1, 2014 through December 24,
2014.
But I keep getting 40+ lines of information and I can't seem to get a join statement to work correctly.
I was trying this but I keep getting invalid identifier.
SELECT
CUSTOMER.CUSTOMER_NAME, CUSTOMER_CUSTOMER_NAME, CUSTOMER.CUSTOMER_ADDRESS
FROM CUSTOMER
INNER JOIN
CUSTOMER ON CUSTOMER.CUSTOMER_ID = CUSTOMER_INVOICE.CUSTOMER_ID;
You have a good first attempt.
Your first problem comes from INNER JOIN CUSTOMER - you are already selecting from CUSTOMER, so why JOIN it with CUSTOMER? You should be joining with CUSTOMER_INVOICE instead:
SELECT
CUSTOMER.CUSTOMER_NAME, CUSTOMER.CUSTOMER_ADDRESS
FROM CUSTOMER
INNER JOIN
CUSTOMER_INVOICE ON CUSTOMER.CUSTOMER_ID = CUSTOMER_INVOICE.CUSTOMER_ID;
I've also fixed the other problem with your SELECT, before it was this:
SELECT
CUSTOMER.CUSTOMER_NAME, CUSTOMER_CUSTOMER_NAME, CUSTOMER.CUSTOMER_ADDRESS
Yet there is no column or alias defined as CUSTOMER_CUSTOMER_NAME. So it will throw you an invalid identifier error.
This will return all of the customers with respective customer invoices - now we need to filter it down to invoices with the coupons set to YES using WHERE:
SELECT
CUSTOMER.CUSTOMER_NAME, CUSTOMER.CUSTOMER_ADDRESS
FROM CUSTOMER
INNER JOIN
CUSTOMER_INVOICE ON CUSTOMER.CUSTOMER_ID = CUSTOMER_INVOICE.CUSTOMER_ID
WHERE
CUSTOMER_INVOICE.COUPON_YESNO = 'YES';
and now filter the result-set down further to work with the particular date range from your question. I'll let you figure this part out unless you're having difficulty understanding the WHERE.

Summing Sales Data Access

I'm just starting out with SQL, I have been playing around with simple select queries and grouping data, now I want to pull some actually useful data out of our database for analysis. The data is organized as follows:
Access 2010 Database
I didn't set it up, I know it isn't set up as it should be
I can't change data, only poll
-Customers are kept in one table
-Closed orders are kept in another table (each line item is listed with invoice #, date closed, Customer ID as well as other info)
-Archived closed orders table keep sales records that are a year + old (table is laid out exactly the same as Closed order table)
I want to start with a simple query, list all the customers from a certain branch and their past year totals. Here's what I have tried:
SELECT CUSTOMERS.Company, CUSTOMERS.[Ship City], (SELECT SUM (CLOSEDORDERS.Quant*CLOSEDORDERS.SellPrice) FROM CLOSEDORDERS WHERE CUSTOMERS.ID = CLOSEDORDERS.CustID) AS LifeTotal
FROM CUSTOMERS, CLOSEDORDERS
WHERE CUSTOMERS.Branch=33;
When I run the query, it asks me to enter a parameter value for CLOSEDORDERS.Quant. What am I doing wrong?
I think this is what you're looking for with an OUTER JOIN:
SELECT CUSTOMERS.Company,
CUSTOMERS.[Ship City],
SUM(CLOSEDORDERS.Quant*CLOSEDORDERS.SellPrice) AS LifeTotal
FROM CUSTOMERS
LEFT JOIN CLOSEDORDERS ON CUSTOMERS.ID = CLOSEDORDERS.CustID
WHERE CUSTOMERS.Branch=33
GROUP BY CUSTOMERS.Company,
CUSTOMERS.[Ship City]
If you only want to return matching results from both tables, then use a standard INNER JOIN instead of the LEFT JOIN.