How to use SUM and MAX in SQL - sql

I want to give the name of the product that has been sold the most overall with its sales quantity. Total Quantity is the sum of products sold - that are the products whose order status (order_status) is Paid or Shipped.
I have the following tables:
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR NOT NULL,
product_price numeric NOT NULL,
product_type product_types NOT NULL,
product_created_at TIMESTAMP NOT NULL DEFAULT NOW()
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
order_store_id INT NOT NULL REFERENCES stores,
order_user_id INT NOT NULL REFERENCES users,
order_status order_states NOT NULL,
order_created_at TIMESTAMP NOT NULL DEFAULT NOW()
CREATE TABLE order_items (
order_id INT references orders,
product_id INT references products,
quantity INT DEFAULT 1 CHECK ( quantity > 0 ),
PRIMARY KEY (order_id, product_id)
I have written the query:
SELECT products.product_name, maxam
FROM products, (SELECT SUM(quantity) AS total FROM order_items) AS foo
WHERE orders.order_id = order_items.order_id AND orders.order_status IN ('Paid', 'Shipped')
GROUP BY orders.order_status
HAVING maxam = MAX(total)
, but I think there are a lot of mistakes (working with sql for the first time)

try this
SELECT top 1 products.product_name, SUM(quantity) as QTY
FROM
orders inner join
order_items
on orders.order_id = order_items.order_id
order_items inner join
products
on order_items.product_id = products.product_id
WHERE orders.order_status IN ('Paid', 'Shipped')
GROUP BY products.product_name
order by qty desc

Working query:
SELECT products.product_name , SUM(quantity) AS QTY
FROM orders JOIN order_items ON orders.order_id = order_items.order_id JOIN products ON order_items.product_id = products.product_id
WHERE order_status IN ('Paid', 'Shipped')
GROUP BY products.product_name
ORDER BY QTY desc LIMIT 1;

Related

SQLite Query testing for multiple row matches

I am a bit stuck trying to query this:
Find all Customers that have ordered the same as Customer Number 250
Schema for database:
Customers(
customerNumber INTEGER, PRIMARY KEY
);
Orders(
orderNumber INTEGER, PRIMARY KEY
customerNumber INTEGER NOT NULL,
FOREIGN KEY (customerNumber) REFERENCES Customers
);
OrderDetails (
orderNumber INTEGER NOT NULL,
productCode TEXT NOT NULL,
PRIMARY KEY (orderNumber, productCode),
FOREIGN KEY (productCode) REFERENCES Products
);
I figured the query:
select DISTINCT customerNumber
FROM Orders Natural
JOIN OrderDetails
WHERE productCode NOT IN (
select productCode
FROM Orders NATURAL JOIN OrderDetails
WHERE customerNumber = 219
)
order by customerNumber;
would be correct but it returns nothing, so clearly I am misunderstanding something.
As you need all customer those are order all the product that 250 order or more than 250 but have same product , so tried with conditional aggregation
select customerNumber
FROM Orders o
JOIN OrderDetails od
on o.orderNumber =od.orderNumber
WHERE od.productCode IN (
select productCode
FROM Orders o
JOIN OrderDetails od
on o.orderNumber =od.orderNumber
WHERE customerNumber = 250
)
group by customerNumber
having count(distinct productCode )>=
(select count(distinct productCode )
FROM Orders o
JOIN OrderDetails od
on o.orderNumber =od.orderNumber
WHERE customerNumber = 250)

Oracle query for customers who buy popular products

I have three tables: customer, order and line items. They are set up as follows:
CREATE TABLE cust_account(
cust_id DECIMAL(10) NOT NULL,
first VARCHAR(30),
last VARCHAR(30),
address VARCHAR(50),
PRIMARY KEY (cust_id));
CREATE TABLE orders(
order_num DECIMAL(10) NOT NULL,
cust_id DECIMAL(10) NOT NULL,
order_date DATE,
PRIMARY KEY (order_num));
CREATE TABLE line_it(
order_id DECIMAL(10) NOT NULL,
line_id DECIMAL(10) NOT NULL,
item_num DECIMAL(10) NOT NULL,
PRIMARY KEY (order_id, line_id),
FOREIGN KEY (item_id) REFERENCES products);
I need to write a query that selects customers, their names and addresses who have purchased items that have been bought by 3 or more people. I have the following query:
SELECT cust_account.cust_id, cust_account.first, cust_account.last, cust_account.address
FROM cust_account
INNER JOIN orders ON cust_account.cust_id = orders.cust_id
INNER JOIN line_it ON orders.order_id = line_it.order_id
GROUP BY cust_account.cust_id, cust_account.last
HAVING COUNT(line_it.item_num) = (
SELECT COUNT (DISTINCT order_num > 3)
FROM line_it
);
Do I even need to make it a subquery? I am a bit lost. Appreciate any help, thanks.
Start with "items bought by 3 or more people". You can get these by doing:
select li.item_id
from line_item li join
order_info oi
on li.order_id = oi.order_id
group by li.item_id
having count(distinct oi.customer_id) >= 3;
Now you want customers in this set. Hmmmm:
select distinct ca.*
from customer_account ca join
orderinfo oi
on ca.customer_id = oi.customer_id join
line_item li
on li.order_id = oi.order_id
where li.item_id in (select li.item_id
from line_item li join
order_info oi
on li.order_id = oi.order_id
group by li.item_id
having count(distinct oi.customer_id) >= 3
);
You can also express this with window functions:
select distinct ca.*
from (select ca.*, count(distinct customer_id) over (partition by li.item_id) as num_customers_on_item
from customer_account ca join
orderinfo oi
on ca.customer_id = oi.customer_id join
line_item li
on li.order_id = oi.order_id
) ca
where num_customers_on_item >= 3;
You can use the following query
SELECT distinct customer_account.* FROM line_item, order_info ,customer_account where item_id in (
--Selecting only item purchased 3 or more
SELECT item_id FROM line_item group by item_id having count(1) >=3
)
and line_item.order_id = order_info.order_id
and customer_account.customer_id = order_info.customer_id
;

Exclusive customers to one item in one category who buy more in period 2 vs period 1

I have two tables: products and orders
CREATE TABLE product (
product_id INTEGER,
product_name CHARACTER VARYING(20),
category_name CHARACTER VARYING(20)
);
CREATE TABLE orders (
order_id INTEGER,
date_id INTEGER,
customer_id INTEGER,
product_id INTEGER,
sales INTEGER
);
Here is some sample data:
INSERT INTO product VALUES (1,'widget','thingamabobs');
INSERT INTO product VALUES (2,'sprocket','thingamabobs');
INSERT INTO product VALUES (3,'gizmo','doodads');
-- 10 orders across 2 dates to 5 customers
INSERT INTO orders VALUES (1,1,1,1,2);
INSERT INTO orders VALUES (1,1,1,3,2);
INSERT INTO orders VALUES (2,1,2,2,3);
INSERT INTO orders VALUES (3,1,3,1,1);
INSERT INTO orders VALUES (4,1,4,1,2);
INSERT INTO orders VALUES (5,1,5,1,1);
INSERT INTO orders VALUES (6,2,1,1,3);
INSERT INTO orders VALUES (6,2,1,3,2);
INSERT INTO orders VALUES (7,2,2,2,3);
INSERT INTO orders VALUES (8,2,3,1,1);
INSERT INTO orders VALUES (8,2,3,2,1);
INSERT INTO orders VALUES (9,2,4,1,1);
INSERT INTO orders VALUES (10,2,5,1,2);
From the above I need to identify thingamabob customers who only purchased widgets and purchased more in the latest period versus prior.
I have written the below query:
WITH otherprod AS (SELECT DISTINCT customer_id
FROM orders o
INNER JOIN product p
ON o.product_id=p.product_id
WHERE category_name='thingamabobs' AND o.product_id<>1 ),
prod AS (SELECT DISTINCT customer_id
FROM orders o
WHERE o.product_id=1
),
solus AS (SELECT p.customer_id
FROM prod p
LEFT JOIN otherprod op
ON p.customer_id=op.customer_id
),
prodpp AS (SELECT customer_id,SUM(sales) AS ppsales
FROM orders o
WHERE o.product_id=1
AND date_id<2
GROUP BY customer_id
),
prodtp AS (SELECT customer_id,SUM(sales) AS sales
FROM orders o
WHERE o.product_id=1
AND date_id>1
GROUP BY customer_id
)
SELECT pp.customer_id
FROM prodpp pp
INNER JOIN prodtp tpp
ON pp.customer_id=tpp.customer_id
INNER JOIN solus s
ON pp.customer_id=s.customer_id
WHERE ppsales<sales;
Which returns the correct result:
customer_id
5
1
(2 rows)
But is there a more efficient way?
I think you can write the query something like this:
select customer_id,
sum(case when date_id = 1 then sales else 0 end) as sales_1,
sum(case when date_id = 2 then sales else 0 end) as sales_2
from (select o.*, p.*,
min(p.product_name) over (partition by o.customer_id) as minpn,
max(p.product_name) over (partition by o.customer_id) as maxpn
from orders o join
products p
on o.product_id = p.product_id
where p.category_name = 'thingamabobs'
) op
where minpn = maxpn and minpn = 'widget'
group by custoemr_id
having sales_2 > sales_1;
This is based off of your description, not your code.
Notes:
The subquery calculates the minimum and maximum product for each customer in the "thingamabobs" group.
They are the same when the minimum and maximum are the same and they have the value you are looking at.
I don't follow the date logic, for conversion from dates to periods. Perhaps there should be more sophisticated date logic in the outer case expressions.

SQL: How can I retrieve total amount from joined tables?

My tables
CREATE TABLE Customers (
id SERIAL PRIMARY KEY,
firstname VARCHAR(50),
lastname VARCHAR(50)
);
CREATE TABLE Payments (
id SERIAL PRIMARY KEY,
amount INT,
customer_id INT,
CONSTRAINT fk_CustomerPayment FOREIGN KEY (customer_id) REFERENCES Customers (id)
);
I want to get total payment amount for all customers. Here is my try:
SELECT SUM(p.amount)
FROM Customers c
JOIN Payments p
ON c.id = p.customer_id
GROUP BY p
select sum(p.amount) as total
from
customers c
inner join
payments p on c.id = p.customer_id
If there can be null values in payments.customer_id the join condition will exclude them.
Or cheaper without the join:
select sum(amount) as total
from payments
where customer_id is not null
remove group by from query..
SELECT SUM(p.amount)
FROM Customers c
JOIN Payments p
ON c.id = p.customer_id

SQL query select client that has the most orders placed

I want to select the client that has the most orders placed:
I have 2 tables :
CREATE TABLE customers(
customerid INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME CHAR(50) NOT NULL,
address CHAR(100) NOT NULL,
city CHAR(30)NOT NULL
);
CREATE TABLE orders(
orderid INT UNSIGNED NOT NULL,
customerid INT UNSIGNED NOT NULL,
);
This is what i am trying to do:
SELECT customers.customerid, customers.name,orders.orderid, COUNT(customerid)
AS CostumerCount
FROM customers
INNER JOIN orders
ON customers.customerid=orders.orderid;
How can i make this?
Since it is not necessarily for you what RDBMS you are using, then let me assume that you are using MySQL, and you are looking for the customer that has the highest orders count:
SELECT
customers.customerid,
customers.name,
COUNT(orders.orderid) AS Orderscount
FROM customers
INNER JOIN orders ON customers.customerid = orders.customerid
GROUP BY customers.customerid,
customers.name
ORDER BY Orderscount DESC
LIMIT 1;
your create table contain wrong syntax
try this
CREATE TABLE customers(
customerid INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME CHAR(50) NOT NULL,
address CHAR(100) NOT NULL,
city CHAR(30)NOT NULL
);
CREATE TABLE orders(
orderid INT UNSIGNED NOT NULL,
customerid INT UNSIGNED NOT NULL
); ^----remove comma ',' from here
and your query works good just replace COUNT(customerid) by COUNT(customers.customerid)
try it here
SELECT customers.customerid, customers.name,orders.orderid, COUNT(customers.customerid)
AS CostumerCount
FROM customers
INNER JOIN orders
ON customers.customerid=orders.orderid;
SELECT customers.customerid, customers.name,
orders.orderid, COUNT( orders.customerid ) AS CostumerCount
FROM customers
INNER JOIN orders ON customers.customerid = orders.customerid
For SQL SERVER;
SELECT TOP (1) * FROM (
SELECT customers.customerid, customers.name, COUNT(*) AS CostumerCount
FROM customers INNER JOIN orders
ON customers.customerid=orders.customerid
GROUP BY customers.customerid, customers.name
) A
ORDER BY CostumerCount DESC
SELECT * FROM Customers WHERE cno = (
SELECT cno FROM (
SELECT count(*) as ordCount, cno
FROM ORDERS
GROUP BY cno HAVING ordCount >= (
SELECT max(ordCount)
FROM (
SELECT count(*) as ordCount, cno
FROM ORDERS
GROUP BY cno
)
)
)
)
I have edited the first answer because if you have more clients with the same number of orders you will only get the first one!
SELECT
customers.customerid,
customers.name,
COUNT(orders.orderid) AS Orderscount
FROM customers
INNER JOIN orders ON customers.customerid = orders.customerid
GROUP BY customers.customerid,
customers.name
HAVING Orderscount = (
SELECT COUNT(id) AS Orderscount
FROM orders
GROUP BY customerid
ORDER BY Orderscount DESC
LIMIT 1
)