I have the (drastically simplified) schema of three tables as follows:
I'm looking to query the database for customers without orders in a certain date range. I know LEFT JOIN can be used to simply find customers with no invoices etc., but I am unsure how I can leverage JOIN (or perhaps even OUTER JOIN) to introduce a date range.
Is this possible using SQL JOIN or should I be looking to use NOT IN syntax to find customers that aren't in a given result set?
My database software is MySQL.
Try this:
select c.*
from customers c left join
invoices i
on c.code = i.customer_code and
i.date between DATE1 and DATE2
where i.customer_code is null;
The key idea is to put the date range in the on clause.
Related
My database has 3 tables. One is called Customer, one is called Orders, and one is called RMA. The RMA table has the info regarding returns. I'll include a screen shot of all 3 so you can see the appropriate attributes. This is the code of the query I'm working on:
SELECT State, SKU, count(*)
from Orders INNER JOIN Customer ON Orders.Customer_ID = Customer.CustomerID
INNER JOIN RMA ON Orders.Order_ID = RMA.Reason
Group by SKU
Order by SKU
LIMIT 10;
I'm trying to get how much of each product(SKU) is returned in each state(State). Any help would really be appreciated. I'm not sure why, but anytime I include a JOIN statement, my query takes anywhere from 5 minutes to 20 minutes to process.
[ Customer table]
!2[ RMA table]
!3
Your query should look like this:
SELECT c.State, o.SKU, COUNT(*)
FROM Orders o INNER JOIN
Customer c
ON o.Customer_ID = c.CustomerID JOIN
RMA
ON o.Order_ID = RMA.Order_Id
GROUP BY c.State, o.SKU
ORDER BY SKU;
Your issue is probably the incorrect JOIN condition between Orders and RMA.
If you have primary keys properly declared on the tables, then this query should have good-enough performance.
Given you are joining with an Orders table I'm going to assume this table contains all the orders that the company has ever done. This can be quite large and would likely cause the slowness you are seeing.
You can likely improve this query if you place some constraint on the Orders you are selecting, restricting what date range you use is common way to do this. If you provide more information about what the query is for and how large the dataset is everyone will be able to provide better guidance as to what filters would work best.
I currently have 4 SQL tables that look like this:
CustomersTable, RegistrationTable, OrdersTable and OffersTable
enter image description here
I need to write a SELECT statement that retrieves all customers from the CustomersTable (all the fields) that contain rows that match the RegistrationTable Or rows that match the OrdersTable with status "closed", in the result table shouldn't display duplicate customers.
As you realized, CustomersTable and RegistrationTable have the field in common "customerId", but between CustomersTable and OrdersTable there is no field in common. However there is another table (OffersTable) which has the fields "customerId" and "ID", to query information to Customers and Orders table respectively. Remember that a customer who appears in OfferTable not necessarily will appear in OrderTable or just the status is NOT "Closed"
So based on my example tables above, if I were to run the query, it would return the following result:
enter image description here
In the result table shouldn't display duplicate customers.
I really appreciate your help.
Thanks for your time !!
Note - I am using MySQL
Try Using "Union" and "inner join" with every table Like below:
Select Customers.* from Customers inner join Registration on Customers. customerId= Registration.customerId
union
Select Customers.* from Customers inner join offers on Customers.customerId=offers.customerId
inner join Orders on orders.Id= offers.Id and Orders.Status='closed'
I would think exists or in, given what you want. Your description of the table is a bit cumbersome -- which is why sample data in the question is so helpful.
The resulting query would look something like this:
select c.*
from customers c
where exists (select 1 from registrations r where r.customerid = c.customerid) or
exists (select 1
from offers o join
orders oo
on o.id = oo.orderid
where o.customerid = c.customerid and
oo.status = 'closed'
);
The column names may not be quite right.
I have 3 tables:
1. products(product_id,name)
2. orders(id,order_id,product_id)
3. factors(id,order_id,date)
I want to retrieve product names(products.name) where have similar order_id on a date in two last tables.
I use this query for this purpose:
select products.name
from products
WHERE products.product_id ~IN
(
SELECT distinct orders.product_id FROM orders WHERE
order_id IN (select order_id FROM factors WHERE
factors.datex ='2017-04-29') GROUP BY product_id
)
but no result. where is my mistake? how can I resolve that? thanks
Your query should be fine. I am rewriting it to make a few changes to the structure, but not the logic (this makes it easier for me to understand the query):
select p.name
from products p
where p.product_id in (select o.product_id
from orders o
where o.order_id in (select f.order_id
from factors f
where f.datex = '2017-04-29'
)
) ;
Notes on the changes:
When using multiple tables in a query, always qualify the column names.
Use table aliases. They make queries easier to write and to read.
SELECT DISTINCT and GROUP BY are unnecessary in IN subqueries. The logic of IN already handles (i.e. ignores) duplicates. And by explicitly including the operations, you run the risk of a less efficient query plan.
Why might your query not work?
factors.datex has a time component. If so, then this will work date(f.datex) = '2017-04-29'.
There are no factors on that date.
There are no orders that match factors on that date.
There are no products in the orders that match the factors on that date.
In factors table column name is date so it should be -
factors.date ='2017-04-29'
You have written -
factors.datex ='2017-04-29'
I have to get data from two SQL tables but I am unsure of what join to use and the same tables have the same customers_id table would I use an inner join?
table - customers
customers_id
customers_firstname
customers_lastname
customers_email_address
table - orders
customers_id
customers_street_address
customers_suburb
customers_city
customers_postcode
customers_state
customers_country
It depends on what results you want. If you want every record in Customers regardless of whether there is a matching record in orders the you would use an LEFT OUTER JOIN. If not you would use an INNER JOIN. This is the article I typically refer people to for a basic explanation of joins.
An INNER JOIN would look like this:
SELECT c.customers_id,
c.customers_firstname,
c.customers_lastname,
o.customers_street_address,
o.customers_city,
o.customers_postcode,
o.customers_state
FROM customers as c
INNER JOIN orders as o
ON c.customers_id = o.customers_id
I purposely did not do select *. Try to get into the habit of only selecting the columns you want from tables instead of everything.
The join you should use depends on which information you are trying to retain, based on the customer ID. If you're looking to retain all of the information from customers even if there is no match with orders you would use a left join. Conversely, if you wanted to retain all the information from orders even if there were no match with customers you would use a right join.
If you want to return all of the information, and combine rows which have a match, use a full join. Finally, you can use an inner join if you only want the rows which have a match from either table.
the same tables have the same customers_id table
I think you meant to say they have a common column, being customers_id, in which case you can use NATURAL JOIN.
INNER JOIN Ya you can use it.
You can write below query to get your all data from two tables.I am going to write full join query for you.y
select customers.customers_firstname,
customers.customer_lastname,
orders.customers_city
from customers
INNER JOIN orders
ON customer.customers_id = orders.customers_id
With 1001 possibilities to use MySQL, I've come up with a requirement for myself that I want to figure out, but don't know how. I also ran a Google Search of course and checked Stack Overflow and MySQL Docs, but I didn't get the answer I was looking for.
The situation:
I have 2 tables. One called and containing customers and one containing customer_progress . For your imaging, the customer_progress table can optionally contain data about the progress/status for a customer.
My goal was to join the data from the two tables, and put the customers that do have progress data on top, followed by the customers that do not have progress data; all in 1 query.
So I started writing a query, much like the following:
SELECT
*
FROM
customers AS c
LEFT JOIN
customer_progress AS p
ON
p.customer_id = c.id AND p.year = 2011 // Joining them and selecting the progress for a certain year.
WHERE
c.active = 1;
How can I put the customers that do have a progress record first, and then afterwards all the customers that do not have a progress record?
I don't know if I am going the right way with the query or that I need to approach this from a whole different angle. Using a ORDER BY made no sense.
You need to select a customer progress_field that you can order by so that you add something like
order by custer_progress_field desc;
at the end of your select statement.
For example:
SELECT
c.filed1, p.field1
FROM
customers AS c
LEFT JOIN
customer_progress AS p
ON
p.customer_id = c.id AND p.year = 2011 // Joining them and selecting the progress for a certain year.
WHERE
c.active = 1;
Order by p.field1 desc;
You need to add something like
ORDER BY IF(p.customer_id IS NULL,1,0), [other fields]
// or you can do just if sorting by customer_id is acceptable
ORDER BY p.customer_id DESC
You can check more details about how columns with NULL values are treated by ORDER BY on http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html