List Customer And Product Without Sale - sql

Need to show the following columns (3) using UNION to return:
All customers who do not have an invoice
All products that were not sold
Category: Is this related to "customer" or "product"? Print "customer or "product"
ID: Customer.id (category="customer") or product.id (category="product")
Name: customer.customer_name (category="customer") or product.product_name (category="product")
Tables:
Customer
id
customer_name
city_id
customer_address
contact_person
email
phone
Product
id
sku
product_name
product_description
current_price
quantity_in_stock
Invoice
id
invoice_number
customer_id
user_account_id
total_price
time_issued
time_due
time_paid
time_canceled
time_refunded
Invoice_Item
id
invoice_id
product_id
quantity
price
line_total_price
So far have the following:
SELECT
category,
CASE
WHEN category = 'customer' THEN c.id
WHEN category = 'product' THEN p.id
END AS 'id',
CASE
WHEN category = 'customer' THEN c.customer_name
WHEN category = 'product' THEN p.product_name
END AS 'name'
FROM
(
SELECT
CASE
WHEN c.id = c.id THEN 'customer'
WHEN p.id = p.id THEN 'product'
END as 'category'
FROM
customer as c
LEFT Join -- Left join to show all customers even those with & without invoices
invoice as i
ON c.id = i.customer_id
AND i.id IS NULL -- Gives me all customers who do not have an invoice
JOIN invoice_item as ii
ON i.id = ii.invoice_id
Join product p
ON p.id = ii.product_id
) tb1
UNION ALL
SELECT
category,
CASE
WHEN category = 'customer' THEN c.id
WHEN category = 'product' THEN p.id
END AS 'id',
CASE
WHEN category = 'customer' THEN c.customer_name
WHEN category = 'product' THEN p.product_name
END AS 'name'
FROM
(
SELECT
CASE
WHEN c.id = c.id THEN 'customer'
WHEN p.id = p.id THEN 'product'
END as 'category'
FROM
product as p
LEFT JOIN -- Left join to show all products even those that sold and not sold
invoice_item as ii
ON p.id = ii.product_id
AND ii.invoice_id IS NULL -- Gives me products that didnt sell
JOIN invoice as i
ON ii.invoice_id = i.id
) tb2
Open to any suggestions as I'm stuck trying to figure out how to show the category as either "product" or "customer". Thanks in advance!

Considering your data model and requirements, you should try the below SQLs. You can easily perform UNION with both the SQLs.
First SQL returns this list --> All customers who do not have an invoice
select 'customer' as category, c.id as id, customer_name as name
from customer c
left join invoice i on c.id = i.customer_id
where i.id is null
Second SQL returns this list --> All products that were not sold
select 'product' as category, p.id as id, product_name as name
from product p
left join invoice_item ii on p.id = ii.product_id
where ii.id is null;

Well, it is older than 6 months but still, answer would be:
select 'customer' as category, c.id as id, customer_name as name
from customer c
left join invoice i on c.id = i.customer_id
where i.id is null
union
select 'product' as category, p.id as id, product_name as name
from product p
left join invoice_item ii on p.id = ii.product_id
where ii.id is null;

SELECT 'customer' as category,id,customer_name FROM customer
WHERE id NOT IN(SELECT customer_id FROM invoice)
UNION
SELECT 'product' as category,id,product_name FROM product
WHERE id NOT IN(SELECT product_id FROM invoice_item);

The actual question is all customers details even those without invoices and all products even those which are not sold.
SELECT c.customer_name,
p.product_name,
Coalesce((ii.quantity), 0) AS quantity
FROM customer c
LEFT JOIN invoice i
on c.id = i.customer_id
LEFT JOIN invoice_item ii
ON ii.invoice_id = i.id
LEFT JOIN product p
ON ii.product_id = p.id
ORDER BY c.customerid,
p.product_id,
ii.id
UNION
SELECT 'N/A',
p.product_name,
0
FROM products p
ORDER BY p.id

Related

How to list products that belong to more than 3 private categories

What's the SQL to find the list of products that belong to more than 3 private categories.
I tried this:
SELECT
products.*
FROM
products
INNER JOIN
product_categories
ON
products.product_id = product_categories.product_id
INNER JOIN
categories
ON
product_categories.category_id = categories.category_id
WHERE
categories.is_private = 1
GROUP BY
categories.category_id
HAVING
COUNT(categories.category_id) > 3
Thanks!
Your query would be correct if you aggregated by products.product_id -- well, depending on the database, you might need to include other columns in the SELECT. But it is valid SQL assuming that product_id is unique in that table.
If you only want the product ids you don't need the products table:
select pc.product_id
from product_categories pc join
categories c
on pc.category_id = c.category_id
where is_private = 1
group by pc.product_id
having count(*) > 3;
you need every product witch .... so you should do group by on productID.also you can add other columns of products that you need in both 'select' and 'group by'
SELECT
products.product_id,products.name
FROM
products
INNER JOIN
product_categories
ON
products.product_id = product_categories.product_id
INNER JOIN
categories
ON
product_categories.category_id = categories.category_id
WHERE
categories.is_private = 1
GROUP BY
products.product_id,products.name
HAVING
COUNT (categories.category_id) > 3
To get all columns of products:
SELECT products.*
FROM products p
WHERE product_id in (SELECT pc.product_id
FROM product_categories pc
INNER JOIN categories c ON pc.category_id = c.category_id
WHERE c.is_private = 1
GROUP BY c.category_id
HAVING COUNT(c.category_id) > 3)
Check this out!
select * from products where product_id in
(select pc.product_id from product_categories inner join categories c on
pc.category_id=c.category_id where c.is_private=1
group by c.category_id having count(c.category_id)>3)

Customer product sale query incorrect result in sql server 2016

My DDL looks like below:
CREATE TABLE CUSTOMER
(
ID INT PRIMARY KEY,
CUSTOMER_NAME VARCHAR(50),
CITY_ID INT,
)
CREATE TABLE product
(
id int,
sku VARCHAR(50),
product_name varchar(100),
stock_qty int
)
create table Invoice
(
id int,
invoice_number varchar(100),
customer_id int
)
CREATE TABLE Invoice_item
(
id int,
invoice_id int,
product_id int,
quantity decimal(5,2),
price decimal(5,2),
line_total_price decimal(5,2)
)
I am trying to get sales details of all customer and products
output should return all customer even customer without invoices and
also all product even those product that were not sold.
I need to print customer even not have invoice and even those product
that were not sold
than customer and product as NA and quantity as o
Code i have written:
SELECT ISNULL(c.customer_name,'N/A')AS customer_name,ISNULL(p.product_name,'N/A') AS product_name,
sum(ISNULL(invitm.quantity,'0')) as quantity
FROM customer as c left outer join product as p
on c.id = p.id
left outer join invoice as inv on c.id = inv.id
left outer join invoice_item as invitm on c.id = invitm.id
group by c.customer_name,p.product_name
But this is giving incorrect result. am i doing any mistake with join. please share your suggestion
If you want all customer and product combinations, then I would suggest:
select c.customer_name, p.product_name,
coalesce(sum(ii.quantity), 0) as quantity
from customer c cross join
product p left join
invoice i
on c.id = i.customer_id left join
invoice_item ii
on ii.invoice_id = i.id and ii.product_id = p.id
group by c.customer_name, p.product_name;
If you want all customer/product combinations that exist and then extras for the customers and products that don't exist, I would suggest union all:
select c.customer_name, p.product_name,
coalesce(sum(ii.quantity), 0) as quantity
from invoice i join
customer c
on c.id = i.customer_id join
invoice_item ii
on ii.invoice_id = i.id join
product p
on ii.product_id = p.id
group by c.customer_name, p.product_name
union all
select c.customer_name, null, 0
from customer c
where not exists (select 1 from invoice i where i.customer_id = c.id)
union all
select null, p.product_name, 0
from product p
where not exists (select 1 from invoice_item ii where ii.product_id = p.id);
Maybe like this (I have not checked syntax) - all your joins were totally wrong; you need to join on corresponding fields (foreign keys), not on id-s:
SELECT ISNULL(c.customer_name,'N/A')AS customer_name,ISNULL(p.product_name,'N/A') AS product_name,
sum(ISNULL(invitm.quantity,'0')) as quantity
FROM customer as c full outer join product as p
on c.product_id = p.id
left outer join invoice as inv on c.id = inv.customer_id
left outer join invoice_item as invitm on invitm.invoice_id = inv.id and invitm.product_id = p.id
group by c.customer_name,p.product_name
This is actually a interview question. Below query might be correct:
SELECT c.customer_name,
p.product_name,
Coalesce((ii.quantity), 0) AS quantity
FROM customer c
LEFT JOIN invoice i
on c.id = i.customer_id
LEFT JOIN invoice_item ii
ON ii.invoice_id = i.id
LEFT JOIN product p
ON ii.product_id = p.id
ORDER BY c.customerid,
p.product_id,
ii.id
UNION
SELECT 'N/A',
p.product_name,
0
FROM products p ORDER p.id

Left join when there are lots of matched rows from right table

I have two tables.
Product(id, name)
LineItem(id, product_id, order_id)
Order(id, state)
Order can have many products. One product can belong to many orders at the same time.
I would like to select Products, which don't have orders with specific statuses(i.e. 1, 2).
My query is
SELECT products.id, products.price
FROM "products"
LEFT OUTER JOIN line_items ON line_items.product_id = products.id
LEFT OUTER JOIN orders ON orders.id = line_items.order_id AND orders.status IN (1, 2)
WHERE (products.price > 0) AND (orders.id IS NULL) AND "products"."id" = $1
GROUP BY products.id, products.price [["id", 11]]
11 is an id of a product, that should not appear to the result, but it does.
I would like to select Products, which don't have orders with specific statuses(i.e. 1, 2).
SELECT * FROM products p -- I would like to select Products
WHERE NOT EXISTS( -- , which don't have
SELECT *
FROM orders o -- orders
JOIN line_items li ON li.order_id = o.id
WHERE li.product_id = p.id
AND o.status IN (1,2) -- with specific statuses(i.e. 1, 2).
);
select p.id, p.name
from products p
join lineitem l on l.product_id = p.id
join `order` o on l.order_id = o.id
group by p.id, p.name
having sum(case when o.state in (1,2) then 1 else 0 end) = 0
The idea is to start with the products table and use left join to find orders with 1 or 2. If they don't exist, then you want the product:
select p.id, p.name
from product p left join
lineitem li
on li.product_id = p.id left join
orders o -- a better name for the table
on li.order_id = o.id and
o.state in (1, 2)
where o.id is null
group by p.id, p.name;

SQL nested SELECT with JOIN

I wasted all the day on one query without success , SOS I need a help :) with a given #CustomerId , I need to query all the Products that linked to customer seller can sell but not sold to him before , the Commissions table is indication of what products seller can sell
Thanks in advance
SELECT sellableProduct
FROM (SELECT Comissions.ProductId AS sellableProduct, Sellers.SellerId AS sellableSeller FROM Comissions INNER JOIN Sellers ON Comissions.SellerId=Sellers.SellerId INNER JOIN Customers ON Sellers.SellerId=Customers.SellerId WHERE Customers.CustomerId = #customerid) AS tblSellable
LEFT JOIN (SELECT Sales.ProductId AS soldProduct, Customers.SellerId as soldSeller FROM Customers INNER JOIN Sales ON Customers.CustomerId=Sales.CustomerId WHERE Customers.CustomerId = #customerid) AS tblSold
ON tblSellable.sellableProduct=tblSold.soldProduct AND tblSellable.sellableSeller=tblSold.soldSeller
WHERE tblSold.soldProduct IS NULL
this way you avoid time-consuming IN statements
If a Customer can only have one Seller, then you can omit the seller link:
SELECT sellableProduct
FROM (SELECT Comissions.ProductId AS sellableProduct FROM Comissions INNER JOIN Sellers ON Comissions.SellerId=Sellers.SellerId INNER JOIN Customers ON Sellers.SellerId=Customers.SellerId WHERE Customers.CustomerId = #customerid) AS tblSellable
LEFT JOIN (SELECT Sales.ProductId AS soldProduct FROM Sales WHERE Sales.CustomerId = #customerid) AS tblSold
ON tblSellable.sellableProduct=tblSold.soldProduct
WHERE tblSold.soldProduct IS NULL
Basically, you're looking for products that have a record in commissions, but not in sales. Using :id to denote the specific ID:
SELECT *
FROM products
WHERE productid IN (SELECT productid
FROM commissions
WHERE sellerid = :id) AND
productid NOT IN (SELECT productid
FROM sales
JOIN customers ON sales.customerid = cusomers.customerid
WHERE sellerid = :id)
Would this work?
SELECT sell.*, prod.* FROM
Sellers sell
INNER JOIN Customers cust ON cust.SellerId = sell.SellerId
LEFT JOIN Commissions comm ON sell.SellerId = comm.SellerId
LEFT JOIN Products prod ON prod.ProductId = comm.ProductId
WHERE prod.ProductId NOT IN (
SELECT ProductId
FROM Products p INNER JOIN
Sales s ON s.ProductId = p.ProductId
WHERE s.CustomerId = #CustomerId
It get all the sellers and the respective product from commission, where the product Id is NOT associated with any sale of the client

Getting extra data from the join table

Ok so i have this structure
PRODUCTS
* PRODUCT_ID (primary key)
* PRODUCT_NAME
CATEGORIES
* CATEGORY_ID (primary key)
* CATEGORY_NAME
* CODE
PRODUCT_CATEGORIES_MAP
* PRODUCT_ID (primary key, foreign key to PRODUCTS)
* CATEGORY_ID (primary key, foreign key to CATEGORIES)
* QUANTITY
I am using this query
SELECT * FROM `products`
where id in (
SELECT `product_id`
FROM `categorizations`
WHERE category_id = (
SELECT id
FROM `categories`
where code = 'something'))
this works great but i am just getting a list of products. I need the quantity of each one one in the join table
The table names in your explanation are different from your sample query. I used the ones from your query.
SELECT p.product_id ,
p.product_name,
pc.quantity
FROM `products` p
JOIN `categorizations` pc
ON p.id = pc.`product_id`
JOIN `categories` c
ON c.id = pc.category_id
WHERE c.code = 'something'
sql's a bit rusty but here goes
select PRODUCT_ID, PRODUCT_NAME, QUANTITY
from PRODUCTS as A, PRODUCTS_CATEGORIES_MAP as B, CATEGORIES as C
where A.PRODUCT_ID = B.PRODUCT_ID
and C.CATEGORY_ID = B.CATEGORY_ID
and C.CODE = 'something'
You may want to sum over quantity in case product is in more categories.
select p.*,
sum(m.quantity) quantity
from products p
join categorizations m on m.product_id = p.product_id
join categories on c.category_id = m.category_id
and c.code = 'something'
group by p.product_id
Otherwise look at #Martin code
The detail that you want is the quantity of the product and so, why not start by them....you can always retrieve the products because you have the product_id.
SELECT * FROM (SELECT `product_id`, `quantity`
FROM `categorizations`
WHERE category_id = (
SELECT id
FROM `categories`
where code = 'something'))) AS `filtered_categorization`
LEFT JOIN `products`
ON (`products`.`id` == `filtered_categorization`.`product`);
try this...
select
p.*,
c.category_id,
c.category_name,
pcm.quantity
from
products p
inner join product_categories_map pcm on p.product_id = pcm.product_id
inner join categories c on pcm.category_id = c.category_id
where
c.code = 'something'
order by
p.product_id, c.category_id;