I got stucked at the following scenario:
table Orders
order_id, order_date, order_customerid, order_state, order_city
table Customers
customer_id, customer_city, customer_state
I need to duplicate customer_city and customer_state into order_city and order_state, which is currently null. I tried using the following join:
select *
from orders o
inner join customers c
on o.customerid = c.id
and then using an update query. But it appears to be grouping orders by customer, so then it does not reflect the actual number of orders, causing some order_city and order_state to be left empty.
What can I do to update EVERY order inside the order table, knowing that there are many orders from the same customer?
You can use multi-table update syntax.
Something like this would work for you:
update orders
inner join customers on customers.customer_id = orders.order_customerid
set orders.order_state = customers.order_state,
orders.order_city = customers.order_city
where orders.order_state is null
or orders.order_city is null
Related
Consider the following query i tried, there two tables, Orders and Customers, each have column name CustomerID, when i try to display both CustomerID's only one column is displaying, i can't understand why is it so, or am i understanding the basics wrong.
SELECT Customers.CustomerID,Orders.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
When i try to display only one column it is displaying well and good
SELECT Customers.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
and
SELECT Customers.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
So my problem is why I cant display the both.
use alias
SELECT Customers.CustomerID as customerid,Orders.CustomerID as ocustomerid
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
You need to define an alias for each column:
SELECT Customers.CustomerID as customer_id, Orders.CustomerID as order_id
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
This is a peculiarity of some query interfaces. Your first query (which I would write like this) is:
SELECT c.CustomerID, o.CustomerID
FROM customers c INNER JOIN
orders o
ON c.customerid = o.customerid;
This returns two columns, both named CustomerId. Some query interfaces insist that the resulting columns be unique in the result set. Hence, the results ignore "subsequent" columns with the same name.
You can get a flavor of this by using the query as a subquery:
SELECT x.*
FROM (SELECT c.CustomerID, o.CustomerID
FROM customers c INNER JOIN
orders o
ON c.customerid = o.customerid
) x;
This should return an error, because CustomerId is ill-defined.
Three points to remember:
Most databases and query interfaces allow result sets with multiple columns with the same name.
No database allows multiple columns with the same name in a subquery.
You know how to fix this by assigning a column alias, which is a best-practice anyway.
Im trying to write a SELECT statement with a subquery that determines the customer_id and the last_name of the customer
whose credit card expires soonest as shown in my orders table
and for this i want to use a WHERE clause but im stuck since the result only displays one customer...
here is what i have so far. if someone could guide me in the right path..
SELECT customer_id, last_name
FROM customers
WHERE NOT EXISTS
(SELECT card_expires
FROM orders
WHERE customers.customer_id = orders.customer_id
);
While I am not clear on your exact filtering or ordering requirements, I think you may want to start with the following.
SELECT customer_id, last_name, card_expires
FROM customers
left join (
SELECT card_expires
FROM orders
) o on (customers.customer_id = orders.customer_id)
Using this method you can see a full list of all customers and card_expires, and THEN you can start to filter the list down to what you want. You might build up the subquery on orders to select a specific subset of orders. Again I am not clear on what you are trying to do exactly. But by selecting all of the information first you will be able to see all of the information and be able to decide what to filter out.
You may decide you would ALSO like to see more columns from the order table to help you decide which orders to include / exclude.
If you wanted to only see a list of customers that do not have a card_expires entry
SELECT customer_id, last_name, card_expires
FROM customers
left join (
SELECT card_expires
FROM orders
) o on (customers.customer_id = orders.customer_id)
where o.card_expires is null
If you want to see only customers WITHOUT a card that expires in the future.
SELECT customer_id, last_name, card_expires
FROM customers
left join (
SELECT card_expires
FROM orders
where card_expires > now()
) o on (customers.customer_id = orders.customer_id)
where o.card_expires is null
When crafting an SQL statement, something that can make it easier to do is FIRST create an SQL statement which returns ALL of the columns you will use to filter the list by, THEN apply the filter. This will allow you to more easily add and remove criteria until you have it right.
I like to split each criteria on to its own separate line so that I can easily comment lines out with two dashes. EX:
SELECT customer_id, last_name, card_expires
FROM customers
left join (
SELECT card_expires
FROM orders
where card_expires > now()
) o on (customers.customer_id = orders.customer_id)
where 0=0
and o.card_expires is null
-- and last_name = 'Smith'
Use LEFT JOIN/INNER JOIN, i assume you want ORDER BY ASC, since you want the soonest
SELECT customer_id, last_name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
ORDER BY card_expires ASC;
in this cust_id is a foreign key and ords returns the number of orders for every customers
SELECT cust_name, (
SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id
) AS ords
FROM Customers
The output is correct but i want to filter it to retrieve only the customers with less than a given amount of orders, i don't know how to filter the subquery ords, i tried WHERE ords < 2 at the end of the code but it doesn't work and i've tried adding AND COUNT(*)<2 after the cust_id comparison but it doesn't work. I am using MySQL
Use the HAVING clause (and use a join instead of a subquery).....
SELECT Customers.cust_id, Customers.cust_name, COUNT(*) ords
FROM Orders, Customers
WHERE Orders.cust_id = Customers.cust_id
GROUP BY 1,2
HAVING COUNT(*)<2
If you want to include people with zero orders you change the join to an outer join.
There is no need for a correlated subquery here, because it calculates the value for each row which doesn't give a "good" performance. A better approach would be to use a regular query with joins, group by and having clause to apply your condition to groups.
Since your condition is to return only customers that have less than 2 orders, left join instead of inner join would be appropriate. It would return customers that have no orders as well (with 0 count).
select
cust_name, count(*)
from
customers c
left join orders o on c.cust_id = o.cust_id
group by cust_name
having count(*) < 2
working with mySql I would like to list all purchases that customers made on a specific cathegory of products.
So, I had 3 tables: customers (idCustomer, Name) , cathegories (idCategory, CategoryName) and orders (idOrder, idCustomer, idCathegory, Qty, Price)
But I want a listing with ALL of the customers.
Not only the one who bought that specific idCategory
I thought something like:
select sum(Orders.Qty), Customers.Name
from Orders
right join Customers on Orders.idCustomer = Customer.idCustomer
where Orders.idCategory = 'Notebooks'
group by Orders.idCategory
but this statement only lists the records for customers who exists in Orders table.
And I want all of them ( the one who didnt buy, with qty =0 )
thanks in advance
Most people find left join easier to follow than right join. The logic for left join is to keep all rows in the first table, plus additional information from the remaining tables. So, if you want all customers, then that should be the first table.
You will then have a condition on the second table. Conditions on all but the first table should be in the on clause rather than a where. The reason is simple: when there is no match, then the value will be NULL and the where condition will fail.
So, try something like this:
select sum(o.Qty) as sumqty, c.Name
from Customers c left join
Orders o
on o.idCustomer = c.idCustomer and
o.idCategory = 'Notebooks'
group by c.Name;
Finally, the group by should have a relationship to the select clause.
Try this query
select sum(Orders.Qty), Customers.Name
from Customers
right join Orders on Customer.idCustomer = Orders.idCustomer and Orders.idCategory = 'Notebooks'
group by Customers.Name
I have two tables customers and orders, below is the structure.
Table - customers
id
customer_name
Table - orders
id
order_id
customer_id
customers table have customers records and orders table have orders placed by customers,
customer_id in orders table is linked to the id field of customers table.
Now one customer can have zero or one or more than one orders, i want to get the last order placed by customers only.
when i run the following query a simple invisible join, it returns all the orders by the customer
SELECT customers.customer_name,orders.order_id FROM orders,customers WHERE orders.customer_id=customers.id
I have also tried different JOIN statements but cannot get the last order by the customer, i want to get it in one SQL query for all customers.
Thank you in advance for your help.
In MySQL there is just few ways to make it work (that I now actually). The first one is sort your table as desc before the join:
SELECT c.customer_name, o.customer_id, o.order_id,o.id FROM customers c
INNER JOIN orders o
ON o.id = (SELECT id FROM orders WHERE customer_id = c.id ORDER BY id DESC LIMIT 1)
Using in real time is the only way to get it done, but if you need to make some join on not real time you can create a temporary table or a alias table sorting it to make your select, like this:
CREATE TABLE tmp_your_table AS
SELECT * FROM orders ORDER BY id DESC
So now you are able to make this join work:
SELECT c.customer_name, o.customer_id, o.order_id,o.id FROM customers c
INNER JOIN tmp_your_table o ON o.id = tmp_your_table.id
Try this query
SELECT
c.customer_name,
max(o.order_id)
FROM
customers c
INNER JOIN
orders o
ON
o.customer_id = c.id
GROUP BY
c.customer_name
You don't have any date field in the order table so assuming the latest order will be the one which has max(order_id).
Try this query
SELECT
c.customer_name,
o.order_id
FROM
customers c
INNER JOIN
orders o
ON
o.customer_id = c.id
ORDER BY
o.id desc
LIMIT 1;