Ambiguous column name error : SQL count, join, group by - sql

I have two tables as below, one table has number of available units (stock), I'm trying to return the stock count of each product category, and joining it with secondary table to view the description and price etc.
When I run the below query, I get "Ambiguous column name 'productID'."
What am I doing wrong?
SQL Query:
select productID, count (stock)as available_count
from product_units
join product_type ON product_type.description = product_units.productID
group by productID
This returns an error:
Ambiguous column name 'productID'.
Table product_type
productID description price
101 tent 20.00
102 xltent 50.00
Table product_units
unitID productID stock
1 101 1
2 101 1
3 101 1
4 102 1
Orginal SQL query to get stock count, which works:
select productID, count (stock)as available_count
from product_units
group by productID
I'm using SQL Server 2008 R2 with Coldfusion

I think your error is more likely "Ambiguous column name 'productID'." And, I'm guessing the join should be on that field as well:
select product_units.productID, count (stock)as available_count
from product_units
join product_type ON product_type.productID = product_units.productID
group by product_units.productID
To select all rows from the product_type table use a right outer join:
select product_units.productID, count (stock)as available_count
from product_units
right outer join product_type ON product_type.productID = product_units.productID
group by product_units.productID
To select all information from the product type table, do the aggregation first and then join:
select pt.*, pu.available_count
from (select productId, count(stock) as available_count
from product_units
group by productId
) pu join
product_type pt
on pt.productID = pu.productId;

Related

Access subquery for Distinct Count and Count on same table

Hello I have browsed the forum for a while and am asking my first question here. I'm in a bit of a bind and was wondering if I could get some help out. I am using Access and have not found a good answer to the question on the Net yet.
I have a table called tblTransactions for transactions on Access 2013. It looks like this:
Transaction_ID
Customer_No
Prod_ID
Lıcence_ID
1
111
1
1
2
111
1
2
3
222
1
2
4
111
2
1
5
222
2
1
6
222
2
2
7
333
1
1
tblProd looks like:
Prod_ID
Prod_Name
Prod_Price
1
Prod 1
30
2
Prod 2
50
tblLicence looks like:
Lıcence_ID
Lıcence_Name
Lıcence_Price
1
Lıcence 1
80
2
Lıcence 2
100
The customer purchases the product once and may obtain multiple licenses for this product. The product is paid once, but for all licenses owned.
I want to create a summary list for transactions. I cannot print how many different prod it has and how many licenses it has in total next to the customer number.
The output I want should look like this:
Customer_No
Count_Uniq_Prods
Count_Licences
Sum_Prods_Price
Sum_Licences_Price
111
2
3
80
260
222
2
3
80
280
333
1
1
30
80
I tried different methods for the first 3 columns.
When I try with subquery, the Customer number and product count are correct, but it also removes duplicates from licenses.
SELECT C.Customer_No, T2.Count_Uniq_Prods, T2.Count_Licences" & _
FROM" & _
(SELECT T1.Customer_No, T1.Count_Uniq_Prods, Count(Lıcence_ID) As Count_Licences"
FROM" & _
(SELECT DISTINCT Customer_No, Lıcence_ID, Count(Prod_ID) As Count_Uniq_Prods
FROM tblTransactions GROUP BY Customer_No, Lıcence_ID ) AS T1
GROUP BY T1.Customer_No, T1.Count_Uniq_Prods) AS T2
INNER JOIN tblTransactions AS C
ON T2.Customer_No = C.Customer_No" & _
GROUP BY C.Customer_No, T2.Count_Uniq_Prods, T2.Count_Licences;
When I try the left join operation, I can successfully get results for the product and license separately, but when I want to get it in a single table, the results are not what I want.
It's work for Customer_No, Count_Uniq_Prods, Sum_Prods_Price:
SELECT T.Customer_No,
Count(T.Prod_ID), SUM(tblProd.Prod_Price) AS Sum_Prods_Price
FROM ((SELECT DISTINCT Customer_No, Prod_ID FROM tblTransactions ) AS T
LEFT JOIN tblProd ON tblProd.Prod_ID= T.Prod_ID)
GROUP BY T.Customer_No;
It's work for Customer_No, Count_Licences, Sum_Licences_Price:
SELECT T.Customer_No,
Count(T.Lıcence_ID), SUM(tblLicence.[Lıcence_Price]) AS Sum_Licences_Price
FROM ((SELECT Customer_No, Lıcence_ID FROM tblTransactions ) AS T
LEFT JOIN tblLicence ON tblLicence.Lıcence_ID = T.Lıcence_ID)
GROUP BY T.Customer_No
But when I take one as a subquery inside the other, I cannot reach the desired result in both results.
I hope I was able to explain clearly. Thanks in advance for any help.
This should work for you.
My approach was to take your problem and break it down into its constituent elements.
This query retrieves the products in the format that you
requested.
select customer_no, count(t.prod_id) as Count_Uniq_Prods,
sum(p.prod_price) as Sum_Prods_Price
from (
select customer_no, prod_id
from tblTransactions t
group by customer_no, prod_id
) t
inner join tblProd p on
t.prod_id = p.prod_id
group by customer_no
This query retrieves the licenses in the format that you
requested.
select customer_no, count(t. license_id) as Count_Licenses,
sum(l.license_price) as Sum_Licenses_Price
from tblTransactions t
inner join tblLicense l on
t.license_id = l.license_id
group by customer_no
Finally, we put them together and get the following:
select distinct p.customer_no, Count_Uniq_Prods,
Count_Licenses,
Sum_Prods_Price,
Sum_Licenses_Price
from (
select customer_no, count(t.prod_id) as Count_Uniq_Prods,
sum(p.prod_price) as Sum_Prods_Price
from (
select customer_no, prod_id
from tblTransactions t
group by customer_no, prod_id
) t
inner join tblProd p on
t.prod_id = p.prod_id
group by customer_no
) p
inner join (
select customer_no, count(t. license_id) as Count_Licenses,
sum(l.license_price) as Sum_Licenses_Price
from tblTransactions t
inner join tblLicense l on
t.license_id = l.license_id
group by customer_no
) l
on p.customer_no = l.customer_no

Query returns more rows

I have two tables. product_type listing name of products with product id. There are 5 product types which have same product id (1) as they are shared along with 4 other product types with unique product ids (2 to 9). Other table is product. It has the list of customer ids along with what product template id associated with it.
I want to get a list of products which are being used by customer. But I am getting a list with duplicate product rows if there are two customers using the same product. I just want to get a unique list of products being used by all the customers.
Product Table
Product Product_id
AML 1
EDU 1
EXM 1
JEXM 2
JFSA 3
Customer Table
Customer_id Product_id
112 1
113 2
114 1
115 3
116 4
117 2
The query:
SELECT CTE.ProductType, CTE.PRODUCT_ID, DECODE(CT.PRODUCT_ID,NULL,0,1) AS HasCustomer
FROM (
SELECT
LISTAGG(pt.product_type, ', ') WITHIN GROUP (ORDER BY pt.product_type) as ProductType,
pt.PRODUCT_ID
FROM product_type pt
group by pt.PRODUCT_ID) CTE
JOIN CUSTOMER CT ON CT.PRODUCT_ID = CTE.PRODUCT_ID;
Blockquote
I think you want:
SELECT c.customer_id,
LISTAGG(p.product, ', ') WITHIN GROUP (ORDER BY p.product) as products
FROM customers c JOIN
products p
ON c.PRODUCT_ID = p.PRODUCT_ID
GROUP BY c.customer_id;
For each customer, this will give the list of products for the customer.
I based this on your sample data. I don't see the relationship between your query and the sample data.
EDIT:
If you want all products used by any customer, then simply do:
select distinct c.product_id
from customers c;

Calculate value in the query by values from two tables

I have product table like this
PRODUCT_ID PACK_SIZE PACK_PRIZE
3000 5 2.5
3001 5 2.5
3002 5 2.5
3003 5 2.5
Order table
order_id client_id
75001 1024
75002 1033
75003 1030
ITEMS Table
ORDER_ID PRODUCT_ID NUMBER_ORDERED
75001 3936 2
75001 3557 5
75001 3012 3
75001 3236 4
Client Table
CLIENT_ID LAST_NAME STATUS
1021 Smith private
1022 Williams corporate
1023 Browne private
1024 Tinsell corporate
These are sample data I just added these just to show sample data.
I want to select top 2 private clients who has done the orders which are having higher values.
I have problem in selecting orders with max sold amount.
Here's what I'm trying to do.
In this I'm trying to get the Client IDS
SELECT CLIENTS.CLIENT_ID
FROM ORDERS
INNER JOIN ITEMS ON ORDERS.ORDER_ID=ITEMS.ORDER_ID
INNER JOIN PRODUCTS ON ITEMS.PRODUCT_ID =PRODUCTS.PRODUCT_ID
INNER JOIN CLIENTS ON ORDERS.CLIENT_ID = CLIENTS.CLIENT_ID
WHERE ( )
In this i'm trying to select top 2 orders
SELECT TOP 2 ORDERS.ORDER_ID FROM ORDERS
INNER JOIN ITEMS ON ORDERS.ORDER_ID=ITEMS.ORDER_ID
INNER JOIN PRODUCTS ON ITEMS.PRODUCT_ID =PRODUCTS.PRODUCT_ID
WHERE ((PRODUCTS.PACK_PRIZE/PRODUCTS.PACK_SIZE)*(ITEMS.NUMBER_ORDERED));
Gives me errors
FROM Key word not found where expected.
What I want to do is select the order ids from orders which are having highest total and which are not from same client, total should be calculated by finding the unit price by dividing pack_price from pack_size and multiplying it by number_ordered from the items table which is having the matching order id. The ordered clients should be corporate clients.
I'm using oracle 11g.
pack_prize is number pack_size is number
number_ordered is number data type
Oracle doesn't support top 2. Instead use rownum and a subquery:
WITH CTE as (
SELECT ORDERS.ORDER_ID, PRODUCTS.PACK_PRIZE, PRODUCTS.PACK_SIZE, ITEMS.NUMBER_ORDERED
FROM ORDERS INNER JOIN
ITEMS
ON ORDERS.ORDER_ID = ITEMS.ORDER_ID INNER JOIN
PRODUCTS
ON ITEMS.PRODUCT_ID = PRODUCTS.PRODUCT_ID
)
SELECT ORDER_ID
FROM (SELECT CTE.*
FROM CTE
ORDER BY (PACK_PRIZE/PACK_SIZE) * NUMBER_ORDERED DESC
) t
WHERE rownum <= 2;
I'm guessing that the strange where expression is what you are using to determine the best rows.
TOP does not work in oracle. You can use the virtual column ROWNUM or the function ROW_NUMBER() OVER() to get similar functionality.

How to ensure outer join with filter still returns all desired rows?

Imagine I have two tables in a DB like so:
products:
product_id name
----------------
1 Hat
2 Gloves
3 Shoes
sales:
product_id store_id sales
----------------------------
1 1 20
2 2 10
Now I want to do a query to list ALL products, and their sales, for store_id = 1. My first crack at it would be to use a left join, and filter to the store_id I want, or a null store_id, in case the product didn't get any sales at store_id = 1, since I want all the products listed:
SELECT name, coalesce(sales, 0)
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id
WHERE store_id = 1 or store_id is null;
Of course, this doesn't work as intended, instead I get:
name sales
---------------
Hat 20
Shoes 0
No Gloves! This is because Gloves did get sales, just not at store_id = 1, so the WHERE clause has filtered them out.
How then can I get a list of ALL products and their sales for a specific store?
Here are some queries to create the test tables:
create temp table test_products as
select 1 as product_id, 'Hat' as name;
insert into test_products values (2, 'Gloves');
insert into test_products values (3, 'Shoes');
create temp table test_sales as
select 1 as product_id, 1 as store_id, 20 as sales;
insert into test_sales values (2, 2, 10);
UPDATE: I should note that I am aware of this solution:
SELECT name, case when store_id = 1 then sales else 0 end as sales
FROM test_products p
LEFT JOIN test_sales s ON p.product_id = s.product_id;
however, it is not ideal... in reality I need to create this query for a BI tool in such a way that the tool can simply add a where clause to the query and get the desired results. Inserting the required store_id into the correct place in this query is not supported by this tool. So I'm looking for other options, if there are any.
Add the WHERE condition to the LEFT JOIN clause to prevent that rows go missing.
SELECT p.name, coalesce(s.sales, 0)
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id
AND s.store_id = 1;
Edit for additional request:
I assume you can manipulate the SELECT items? Then this should do the job:
SELECT p.name
,CASE WHEN s.store_id = 1 THEN coalesce(s.sales, 0) ELSE NULL END AS sales
FROM products p
LEFT JOIN sales s USING (product_id)
Also simplified the join syntax in this case.
I'm not near SQL, but give this a shot:
SELECT name, coalesce(sales, 0)
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id AND store_id = 1
You don't want a where on the whole query, just on your join

SQL Syntax Issue with getting sum

Ok I have two tables.
Table IDAssoc has the columnsbill_id, year, area_id.
Table Bill has the columns bill_id, year, main_id, and amount_due.
I'm trying to get the sum of the amount_due column from the bill table for each of the associated area_ids in the IDAssoc table.
I'm doing a select statement to select the sum and joining on the bill_ids. How can I set this up so it will have a single row for each of the associated bills in each area_id from the assoc table. There may be three or four bill_ids associated with each area_id and I need those summed for each and returned so I can use this select in another statement. I have a group by set up for the area_id but it still is returning each row and not summing them up for each area_id. I have the year and main_id specified already in the where clause to return the data that I want, but I can't get the sum to work properly. Sorry I'm still learning and I'm not sure how to do this. Thanks!
Edit- Basically the query I'm trying so far is basically just like the one posted below:
select a.area_id, sum(b.amount_due)
from IDAssoc a
inner join Bill b
on a.bill_id = b.bill_id
where Bill.year = 2006 and bill.bill_id = 11111
These are just arbitrary numbers.
The data this is returning is like this:
amount_due - area_id
.05 1003
.15 1003
.11 1003
65 1004
55 1004
I need one row returned for each area_id with the amount_due summed. The area_id is only in the assoc table and not in the bill table.
select a.area_id, sum(b.amount_due)
from IDAssoc a
inner join Bill b
on a.bill_id = b.bill_id
where b.year = 2006 and b.bill_id = 11111
group by a.area_id
You might want to change inner join to left join if one IDAssoc can have many or no Bill:
select a.area_id, coalesce(sum(b.amount_due),0)
from IDAssoc a
left join Bill b
on a.bill_id = b.bill_id
where b.year = 2006 and b.bill_id = 11111
group by a.area_id
You are missing the GROUP BY clause:
SELECT a.area_id, SUM(b.amount_due) TotalAmount
FROM IDAssoc a
LEFT JOIN Bill b
ON a.bill_id = b.bill_id
GROUP BY a.area_id