Problem with Ambiguous Column Name in SQL script - sql

I am new to SQL and using this online compiler.
https://www.programiz.com/sql/online-compiler/
I have the following script and I am getting the error: Error: ambiguous column name: Customers.customer_id
UPDATE
Customers
SET
last_name = 'cow'
FROM
Customers
INNER JOIN Orders ON Customers.customer_id = Orders.customer_id
WHERE
Orders.item = 'Keyboard'
There is a customer_id column in multiple tables, but I am specifying which table to pull each column from. Why is it still saying it is ambiguous?

An UPDATE statement with a join requires an alias for the table being updated. In that case, the following will work as expected. You can also alias the Orders table if desired.
UPDATE C
SET last_name = 'cow'
FROM
Customers C
INNER JOIN Orders
ON C.customer_id = Orders.customer_id
WHERE Orders.item = 'Keyboard';

UPDATE C
SET C.Last_Name = 'cow'
FROM Customers C
INNER JOIN Orders O on O.Customer_id = C.Customer_id
WHERE O.item = 'Keyboard'
updates with joins are a little different than selects.

Related

Query that will result in a list of customer names and the average order value made by each customer

I have a database and I need to create a query that will retrieve a list of customer names and the average order value made by each customer.
I tried:
SELECT c.customer_name, AVG(COUNT(o.order_id)*f.price) AS 'avgorderprice'
FROM Customers c
LEFT JOIN Orders o ON o.customer_id = c.customer_id
INNER JOIN F_in_Or fio ON o.order_id = fio.order_id
INNER JOIN Films f ON fio.film_id = f.film_id;
This is my database structure:
But I get an error, what can be wrong?
But I get an error, what can be wrong ?
You are trying to use an aggregate function Count within an aggregate function and getting a MISUSE OF AN AGGREGATE FUNCTION.
i.e. - > misuse of aggregate function COUNT()
Additionally you are not GROUP'ing your results and thus will receive the entire average rather than a per-customer average.
Aggregate functions work on a GROUP the default being all unless a GROUP BY clause places the rows into GROUPS.
You could instead of AVG(COUNT(o.order_id)*f.price) use sum(f.price) / count(*). However, there is an average aggregate function avg. So avg(f.price)' is simpler.
Additionally as you want an average per customer you want to use a GROUP BY c.customer clause.
Thus you could use :-
SELECT
c.customer_name,
avg(f.price) AS 'avgorderprice' --<<<<< CHANGED
FROM Customers c
LEFT JOIN Orders o ON o.customer_id = c.customer_id
INNER JOIN F_in_Or fio ON o.order_id = fio.order_id
INNER JOIN Films f ON fio.film_id = f.film_id
GROUP BY c.customer_name --<<<<< ADDED
;
This would result in something like :-
I think this should work
SELECT c.customer_name, AVG(f.price) AS 'avgorderprice' FROM Customers c LEFT JOIN Orders o ON o.customer_id = c.customer_id LEFT JOIN F_in_Or fio ON o.order_id = fio.order_id LEFT JOIN Films f ON fio.film_id = f.film_id;

SQL Command not properly ended trying to join 3 tables using query

Hello I am trying to add a Translated_Name column from the Product_descriptions table to my current query that is already joining two tables however the translated_name column is a type NVARCHAR2. Should I be using Inner Join for it or am I completely wrong?
select order_mode,customer_id,product_id from ORDERS
inner join ORDER_items on order_items.ORDER_ID=Orders.ORDER_ID
where exists(select customer_id from customers where orders.customer_id=customers.customer_id)
inner join product_descriptions on product_descriptions.translated_name = Orders.Customer_id
The where clause goes after the joins:
select
order_mode,
customer_id,
product_id
from orders o
inner join order_items oi
on oi.order_id = o.order_id
inner join product_descriptions pd
on pd.translated_name = o.customer_id
where exists(
select 1
from customers c
where o.customer_id = c.customer_id
)
Notes:
table aliases make the query easier to read and write
you should qualify the columns the the from clause with the alias of the table they belong to
I am quite suspicious about the join condition on product_descriptions, which involves customer_id; you might need to review that (without knowing your table structures, it is not possible to tell what the correct condition is)

Update SQL Query with where condition

I added a column in the Orders table called EventId and I have to fill the column with the right value for every row.
I want to achieve it with a more complex sql query like below:
UPDATE [dbo].[Orders] o
SET o.EventId = ????
WHERE o.Id IN (SELECT o.id, s.eventid FROM orders o
INNER JOIN orderskudiscounts osd ON o.id = osd.orderid
INNER JOIN skus s ON osd.skuid = s.id GROUP BY o.id, s.eventid)
I not sure how can I write the query successfully... I have more than 2 thousand mapping to do. So I should use a query...
Thank for any help
I am guessing that you want an update like this:
UPDATE o
SET o.EventId = s.eventid
FROM orders o INNER JOIN
orderskudiscounts osd
ON o.id = osd.orderid INNER JOIN
skus s
ON osd.skuid = s.id;

SQL Oracle (using AND clause)

when I use below code, I get the data of customers who ordered "Planned" or 'obsolete' products, but I want to get data of the customers who ordered both type, changing 'or' to 'and' does not work... please help
SELECT DISTINCT customers.CUST_EMAIL
,ORDERS.ORDER_ID
,PRODUCT_INFORMATION.PRODUCT_NAME
,PRODUCT_INFORMATION.PRODUCT_STATUS
FROM PRODUCT_INFORMATION
INNER JOIN ORDER_ITEMS ON PRODUCT_INFORMATION.PRODUCT_ID = ORDER_ITEMS.PRODUCT_ID
INNER JOIN ORDERS ON ORDER_ITEMS.ORDER_ID = ORDERS.ORDER_ID
INNER JOIN CUSTOMERS ON CUSTOMERS.CUSTOMER_ID = ORDERS.CUSTOMER_ID
WHERE PRODUCT_INFORMATION.PRODUCT_STATUS = 'planned'
OR PRODUCT_INFORMATION.PRODUCT_STATUS = 'obsolete'
ORDER BY CUSTOMERS.CUST_EMAIL;
I'm guessing that you want the following. If you want to get correct answer, rather than guesses, please provide a good representative set of sample data and your expected result based on that sample data.
First part of the query returns Customers that ordered planned products, second part of the query returns Customers that ordered obsolete products. INTERSECT operator returns only those that have ordered both planned and obsolete products.
You don't need explicit DISTINCT any more, because INTERSECT would do it anyway.
I've removed PRODUCT_INFORMATION.PRODUCT_STATUS from the list of returned columns, because with it the result set would be always empty.
I removed ORDERS.ORDER_ID and PRODUCT_INFORMATION.PRODUCT_NAME from result as well. I don't know what should be the correct query, but it is likely that INTERSECT should be done just on CUSTOMER_ID and then, once you get the list of IDs, you can join other tables to it fetching other related details if needed.
The performance of this method is beyond the scope of the question.
SELECT
CUSTOMERS.CUSTOMER_ID
,customers.CUST_EMAIL
FROM
PRODUCT_INFORMATION
INNER JOIN ORDER_ITEMS ON PRODUCT_INFORMATION.PRODUCT_ID = ORDER_ITEMS.PRODUCT_ID
INNER JOIN ORDERS ON ORDER_ITEMS.ORDER_ID = ORDERS.ORDER_ID
INNER JOIN CUSTOMERS ON CUSTOMERS.CUSTOMER_ID = ORDERS.CUSTOMER_ID
WHERE PRODUCT_INFORMATION.PRODUCT_STATUS = 'planned'
INTERSECT
SELECT
CUSTOMERS.CUSTOMER_ID
,customers.CUST_EMAIL
FROM
PRODUCT_INFORMATION
INNER JOIN ORDER_ITEMS ON PRODUCT_INFORMATION.PRODUCT_ID = ORDER_ITEMS.PRODUCT_ID
INNER JOIN ORDERS ON ORDER_ITEMS.ORDER_ID = ORDERS.ORDER_ID
INNER JOIN CUSTOMERS ON CUSTOMERS.CUSTOMER_ID = ORDERS.CUSTOMER_ID
WHERE PRODUCT_INFORMATION.PRODUCT_STATUS = 'obsolete'
ORDER BY CUST_EMAIL
without the script for you tables it's difficult to build a test case and a working query; i'll try with this step:
select order_id from (
SELECT customers.CUSTOMER_ID
,sum(decode(PRODUCT_INFORMATION.PRODUCT_STATUS, 'obsolete', 1, 0)) obsolete
,sum(decode(PRODUCT_INFORMATION.PRODUCT_STATUS, 'planned', 1, 0)) planned
FROM PRODUCT_INFORMATION
INNER JOIN ORDER_ITEMS ON PRODUCT_INFORMATION.PRODUCT_ID = ORDER_ITEMS.PRODUCT_ID
INNER JOIN ORDERS ON ORDER_ITEMS.ORDER_ID = ORDERS.ORDER_ID
INNER JOIN CUSTOMERS ON CUSTOMERS.CUSTOMER_ID = ORDERS.CUSTOMER_ID
WHERE PRODUCT_INFORMATION.PRODUCT_STATUS = 'planned'
OR PRODUCT_INFORMATION.PRODUCT_STATUS = 'obsolete'
group by customers.CUSTOMER_ID)
where obsolete>1 and planned>1
This query should return all the customer id that have items in orders with both the product status (the different product status may be in different orders), if you want to retrieve orders that have products with both status you must change the query removing customer.customer_id and adding orders.order_id. If you provide some script with sample data we can provide a better answer

SQL Query on SQL Server 2008

I'm trying to get only customers that ordered both a "Gas Range" and a "Washer". I'm getting Customers who ordered a "Gas Range" and not a "Washer" and customers with both. I need the customer that meets both conditions. I'm close but a little stuck. Below is the query that I have so far. Please let me know if you need more information.
My Tables - CUSTOMER(CUST_NUM, CUST_NAME), ORDER_LINE(ORDER_NUM, PART_NUM), ORDERS(ORDER_NUM, CUST_NUM), PART(PART_NUM, PART_DESCRIPTION)
SELECT C.CUST_NAME AS [Customer(s) that ordered a Gas Range and Washer]
FROM CUSTOMER C
INNER JOIN ORDERS O
ON C.CUST_NUM = O.CUST_NUM
INNER JOIN ORDER_LINE OL
ON O.ORDER_NUM = OL.ORDER_NUM
INNER JOIN PART P
ON OL.PART_NUM = P.PART_NUM
WHERE P.PART_DESCRIPTION IN ('GasRange','Washer')
GROUP BY C.CUST_NAME
try the following
SELECT C.CUST_NAME AS [Customer(s) that ordered a Gas Range and Washer]
FROM CUSTOMER C
INNER JOIN ORDERS O
ON C.CUST_NUM = O.CUST_NUM
INNER JOIN ORDER_LINE OL
ON O.ORDER_NUM = OL.ORDER_NUM
INNER JOIN PART P
ON OL.PART_NUM = P.PART_NUM
INNER JOIN ORDERS O2
ON C.CUST_NUM = O2.CUST_NUM
INNER JOIN ORDER_LINE OL2
ON O2.ORDER_NUM = OL2.ORDER_NUM
INNER JOIN PART P2
ON OL2.PART_NUM = P2.PART_NUM
WHERE P.PART_DESCRIPTION IN ('GasRange') and P2.PART_DESCRIPTION IN ('Washer')
GROUP BY C.CUST_NAME
EDIT: Had a further look and I'm afraid that this can't be simplified in any other way than using WITH and complicated aggregate functions, which I would say would be more complicated than this - I think the other solution suggested using WITH won't work - it joins incorrectly. You definitely can't remove order line, and you have to use the order twice as well - if it was used once, it will cover only when the customer ordered it within one order, which is not what you wanted ;)
Try this...
So basically you need to join your Parts table again to ensure the same customer ordered a "Gas Range" and a "Washer". An IN, like in your current query functions as an OR therefore you are not getting the expected result.
WITH CTE AS (
SELECT DISTINCT O.CUST_NUM FROM ORDERS O
INNER JOIN ORDER_LINE OL
ON O.ORDER_NUM = OL.ORDER_NUM
INNER JOIN PART P
ON OL.PART_NUM = P.PART_NUM
INNER JOIN PART P2
ON OL.PART_NUM = P2.PART_NUM
WHERE P.PART_DESCRIPTION IN ('GasRange')
AND P2.PART_DESCRIPTION IN ('Washer')
)
SELECT C.CUST_NAME AS [Customer(s) that ordered a Gas Range and Washer]
FROM CUSTOMER C
INNER JOIN CTE O
ON C.CUST_NUM = O.CUST_NUM