My database contains 2 tables called products and product_categories.
Product_categories contain category_id and category_name
Products contain category_id and other irrelevant info for this question.
I need to count the number of products using category_id from the products table and also display their name which is in the product_categories table.
Select * FROM product_categories
displays :
category_id, category_name
1 CPU
2 Video Card
3 RAM
4 Mother Board
5 Storage
And
Select * FROM products
displays (condensed):
category_id
399.77 564.89 1
481.56 554.99 1
4058.99 5499.99 2
3619.14 4139 2
2505.04 3254.99 2
... UPTO CATEGORY_ID 5
Current statement :
SELECT category_id , COUNT (1) AS "TOTAL"
FROM products
GROUP BY category_id;
Output:
Category_id, total
1 70
2 50
5 108
4 60
DESIRED RESULT: I need to display the category id followed by category name and finally the total number of products.
Join those tables:
select p.category_id,
c.category_name,
count(*) as total
from products p join product_categories c on c.category_id = p.category_id
group by p.category_id,
c.category_name
You might want to turn it to outer join if you want to display categories that don't exist in the products table.
I'm new to sql and I'm practicing on a created database in oracle about airbnb listings in amsterdam and berlin. I'm trying to JOIN the Tables HOSTS (host_id, host_name), LISTINGS (which includes all listings in the two city with the attributes listings_id, listings_name, Price, host_id...), Neighbourhoods (Neighbourhood_Group, City and Neighbourhood) and reviews (with review_id, listings_id as a foreign key, reviewer_id, reviewer_name and comment).
Now i want to write a query, which returns the average price, lowest price, highest price, the city (Berlin or Amsterdam), the neighbourhood (Centrum, Alexanderplatz...), the amount of listings and the amount of reviews, all grouped by the distinct neighbourhood, and by the WHERE statement, that limits the returns to those listings, that are hosted by Hosts which have less than 3 listings total.
Now if I run the query without the reviews table and only order it by amount_listings, I get the correct amount of listings per neighbourhood for the column "amount_listings".
SELECT avg(l.price) as Mean_Price,
n.city,
n.neighbourhood,
count (l.listings_id) as amount_listings,
min(l.price),
max(l.price)
FROM listings l
INNER JOIN neighborhood n
ON l.neighbourhood = n.neighbourhood
INNER JOIN hosts h
ON l.host_id = h.host_id
WHERE h.host_id IN (
SELECT host_id
FROM listings
GROUP BY host_id
HAVING count(host_id) < 3
)
GROUP BY n.neighbourhood, n.city
ORDER BY amount_listings DESC;
But if i include the amount of reviews in the query, the results are incorrect. The amount of reviews and the amount of listings column show the wrong amount (too much).
SELECT avg(l.price) as Mean_Price, count(l.listings_id) as amount_listings,
min(l.price), max(l.price), n.city, n.neighbourhood, count(r.review_id) as amount_reviews
FROM listings l
INNER JOIN neighborhood n
ON l.neighbourhood = n.neighbourhood
INNER JOIN hosts h
ON l.host_id = h.host_id
INNER JOIN reviews r
ON l.listings_id= r.listings_id
WHERE h.host_id IN (
SELECT host_id
FROM listings
GROUP BY host_id
HAVING count(host_id) < 3
)
GROUP BY n.neighbourhood, n.city
ORDER BY amount_listings DESC, amount_reviews DESC;
I dont know why the amount_listings and amount_reviews return such wrong results.
Aggregate before joining. You want to join the review count to each listing and then the aggregated listing information to the neighbourhood.
select
lr.mean_price,
n.city,
n.neighbourhood,
lr.amount_listings,
lr.min_price,
lr.max_price,
lr.amount_reviews
from neighborhood n
join
(
select
l.neighbourhood,
min(l.price) as min_price,
max(l.price) as max_price,
avg(l.price) as mean_price,
count(*) as amount_listings,
coalesce(sum(r.reviews_for_listing), 0) as amount_reviews
from listings l
left join
(
select
listings_id,
count(*) as reviews_for_listing
from reviews
group by listings_id
) r on r.listings_id = l.listings_id
where l.host_id in
(
select host_id
from listings
group by host_id
having count(*) < 3
)
group by l.neighbourhood
) lr on lr.neighbourhood = n.neighbourhood
order by n.city, n.neighbourhood;
The cause is that since you are adding a new table with more than 0 rows, records are counted several times, depending on how many reviews are. Since you are only interested in the count of reviews, let's join that instead with a nice old trick:
SELECT avg(l.price) as Mean_Price, count(l.listings_id) as amount_listings,
min(l.price), max(l.price), n.city, n.neighbourhood, r.review_count as amount_reviews
FROM listings l
INNER JOIN neighborhood n
ON l.neighbourhood = n.neighbourhood
INNER JOIN hosts h
ON l.host_id = h.host_id
INNER JOIN (select reviews.listings_id as listings_id, count(*) as review_count from reviews where reviews.listings_id = l.listings_id) r
ON l.listings_id= r.listings_id
WHERE h.host_id IN (
SELECT host_id
FROM listings
GROUP BY host_id
HAVING count(host_id) < 3
)
GROUP BY n.neighbourhood, n.city
ORDER BY amount_listings DESC, amount_reviews DESC;
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;
I have 2 tables one for mobiles and other is for reviews. Reviews table store the reviews of a specific mobile against its mobile id.
Structure of mobiles table.
mobile_id | mobile_name
Structure of reviews table.
review_id | mobile_id | review_body
So far I have written this query.
SELECT c.*, p.review_body
FROM ((select mobile_id, mobile_name from mobiles
WHERE brand_id=1 limit 0,5) c)
left JOIN
(
SELECT mobile_id,
MAX(review_id) MaxDate
FROM reviews
GROUP BY mobile_id
) MaxDates ON c.mobile_id = MaxDates.mobile_id left JOIN
reviews p ON MaxDates.mobile_id = p.mobile_id
AND MaxDates.MaxDate = p.review_id
This query returns the first 5 mobiles from mobile table and their latest (one) review from review table. This is the result it returns.
mobile_id | mobile_name | review_body
Question: But i also want review_count with it. review_count should be equal to total number of reviews a mobile has in reviews table against its mobile_id.
So please tell me how it can be done with a single query that I already have. Any help would be appreciated as i am trying to do this since 24 hours.
I think this would work
SELECT c.*, p.review_body, MaxDates.review_count
FROM ((select mobile_id, mobile_name from mobiles
WHERE brand_id=1 limit 0,5) c)
left JOIN
(
SELECT mobile_id,count(review_id) review_count,
MAX(review_id) MaxDate
FROM reviews
GROUP BY mobile_id
) MaxDates ON c.mobile_id = MaxDates.mobile_id left JOIN
reviews p ON MaxDates.mobile_id = p.mobile_id
AND MaxDates.MaxDate = p.review_id
I have two tabels :
--Products--
idProduct PK
Category FK
Amount
Name
--Category--
idCategory PK
Category Name
if i have 20 products of different categories for example 3 cars 5 planes 9 types of food
how do i get all of them in a new joined table like this
Category Name (from --Category--) Amount of every product (from --Products--)
Cars 3
Planes 9
And so on , i don't have a table with all the elements from each category so what should i do ?
You may looking for simple join with aggregate function
SELECT CategoryName,COUNT(p.Category ) AS [Amount of every product ]
FROM Category c
INNER JOIN Product p ON c.idCategory = p.Category
GROUP BY CategoryName