how to use inner join queries for four tables - sql

I have four tables in my database(notes, expense, category and items).
items table will have so many items on the particular category id
items table have fields
id(primary key), item name(text), unit(text), category id(foreign key)
category table will have just two fields
category table have fields
id(primary key), cat_id(integer), category name(text).
notes table is used to have a record for each shopping note.
notes table have fields
note_id(primary key), date(DATE), total cost(integer).
expense table is used to store the items purchased and its corresponding quantity and price under the particular shopping note using note id as the foreign key
expense table has fields
id(primary key), note_id(foreign key), quantity(integer), price(integer), item_name(text)
When I input the from date,to date and a particular category i need the items under that category that was purchaed between the from and to date.
i need a query that will give output as:
ITEM NAME TOTALQTY TOTALPRICE
carrot 5kg 500
can anyone help me with a solution??

Try this
select A.name, sum(C.unit), A.unit, sum(C.price)
from items as A
INNER JOIN categories as B ON A.category=B._id
INNER JOIN expenses as C ON A.name=C.item_name
INNER JOIN notes as D ON C.Note_id=D._id
where
D.date1 between '2012-01-01' and '2012-03-31' and B.name='Vegetables'
group by
A.name, A.unit

Related

Return stock in a warehouse even if there is no row for that given stock

I have 5 different tables:
Toasters: product name (foreign key to products and primary key), slots, serial
Microwaves: product name (same as toaster), wattage
Products: product name (primary key)
Stock: product (fk to product), warehouse (fk to warehouse), amount
Warehouse: name (primary key)
toasters and microwaves are child tables of products (although its not using postgres inheritance, since there are issues with it). They represent different models of toasters (simplified to just slots and wattage here). Every toaster and microwave has exactly 1 entry in the products table.
Now the goal is to create a query that essentially gives me an amount of all products across all warehouses for a given list of product names. The problem is, that some warehouses may not have a stock entry for a certain product. They also have either one stock per product or none.
I have managed to make it work for a single warehouse:
--join together all 3 product tables and select all desired products
WITH selIProducts AS(
SELECT
--Get the products category by checking if the table is part of the query
(CASE
WHEN toasters IS NOT NULL THEN 'toasters'
WHEN microwaves IS NOT NULL THEN 'microwaves'
ELSE 'ERROR'
END) as category,
products.name as productName,
*
FROM products
--I need a full join to include everything
FULL JOIN toasters ON toasters.name=products.name
FULL JOIN microwaves ON microwaves.name=products.name
WHERE
products.name IN (
'TOASTMASTER 3000',
'TOASTMASTER 3000Rev01',
'A3452 Ultra Microwave Oven',
)
),
warehouseStock AS
(
--only works with one inventory
SELECT * FROM STOCK
WHERE stock.warehouse='WH-1'
)
-- left join to ensure all item categories are included
SELECT COALESCE(warehouseStock.amount,0) as amount,* FROM selProducts
LEFT JOIN warehouseStock ON selIProducts.itemId=warehouseStock.item
It tried replacing WHERE stock.warehouse='WH-1' with WHERE stock.warehouse IN ('WH-1','WH-2') but that doesn't work since the desired product types are only joined once, instead of once per warehouse.
The final result should look like this:
Warehouse productName amount wattage slots category
WH-1 TOASTMASTER 3000 0 null 2 toasters
WH-1 TOASTMASTER 3000Rev01 1 null 3 toasters
WH-1 A3452 Ultra Microwave Oven 1 3000 null microwave
WH-2 TOASTMASTER 3000 2 null 2 toasters
WH-2 TOASTMASTER 3000Rev01 0 null 3 toasters
WH-2 A3452 Ultra Microwave Oven 0 3000 null microwave
I don't know how I am I should get postgres to return a null when there isn't a stock in a given warehouse.
Does anybody have any ideas?
You seem to want all products and all warehouses. That suggests a cross join to generate the rows:
SELECT v.warehouse, p.productname,
COALESCE(s.amount, 0) as amount
FROM selProducts p CROSS JOIN
(VALUES ('WH-1'), ('WH-2')) v(warehouse) LEFT JOIN
stock s
ON p.itemId = s.item AND v.warehouse = s.warehouse;
You might have another source for the warehouses, if you don't want to list them explicitly.
Add a table of warehouses wanted.
WITH selIProducts AS(
SELECT
--Get the products category by checking if the table is part of the query
(CASE
WHEN toasters IS NOT NULL THEN 'toasters'
WHEN microwaves IS NOT NULL THEN 'microwaves'
ELSE 'ERROR'
END) as category,
products.name as productName,
*
FROM products
--I need a full join to include everything
FULL JOIN toasters ON toasters.name=products.name
FULL JOIN microwaves ON microwaves.name=products.name
WHERE
products.name IN (
'TOASTMASTER 3000',
'TOASTMASTER 3000Rev01',
'A3452 Ultra Microwave Oven',
)
),
warehousesWanted AS
(
SELECT *
FROM Warehouse
WHERE name in ('WH-1', 'WH-2')
)
-- left join to ensure all item categories are included
SELECT COALESCE(warehouseStock.amount,0) as amount, *
FROM selIProducts sp
CROSS JOIN warehousesWanted ww
LEFT JOIN Stock ON Stock.itemId = sp.itemId
and ww.Name = Stock.Warehouse;
You may need to correct ON clause as I'm not sure what are proper column names of your real tables.

How to stop a database result from re-appearing once value is taken

I have a car rental project, when renting an available car from database table CAR with car ID as primary key, I insert data into table RESERVATION with reservation ID as primary key and car ID as foreign key from car table.
However, I don't want the car I just rented out to appear as an "available car" to rent. What query should I write in order to hide it?
Select cars.*
from cars, reservation
where ?
You should not need to update any tables to hide the car.
When selecting the list of available cars for display, use this SQL:
SELECT * FROM Car WHERE CarID NOT IN (SELECT CarID FROM Reservation)
This will exclude any cars that have already been reserved. That's the basic idea, anyway.
It's likely that reservations are only good for a certain period, and the user may be attempting to reserve a different period, so you might need something more complicated, like:
SELECT * FROM Car WHERE CarID NOT IN
(
SELECT CarID
FROM Reservation
WHERE StartDate < #DesiredEndDate
AND EndDate > #DesiredStartDate
)
This will provide a list of cars that do not appear in a reservation that overlaps the user's desired reservation time.
You can write a join query as:
Select C.carID
from #Car C
Left join #Reservation R on C.carID = R.carID
where R.reservationID is null

Create row if column does not consist ID from another column

I have database which contain three tables product, product_size (variations) and handbook. Product contains all data about the product, handbook knows which size I have and product_size contain information about products which have size(s) from handbook and also contain size_value.
So I need to insert values in column product_size where size_price will contain price of product, handbook_id = 666 and product_id is ID of products which doesn't have product size. Is there any way to do that?
Product
id
price
name
Product_Size
id
product_id
handbook_id
size_price
Handbook
id
name
All products would mean rows from product table. So size may not be in handbook or may not be in product_size table.
Select p.name
From product p left join
Product_Size ps
On p.id= ps.product_id
Left join Handbook h
On h.id=ps.handbook_id
Where handbook_id is null
You can phrase the insert like this:
insert into product_size (product_id, handbook_id, size_price)
select p.product_id, 666, p.price
from product p
where not exists (select 1
from product_size ps
where ps.product_id = p.product_id and ps.handbook_id = 666
);
Note: This can produce unexpected results if you attempt to run two of these inserts at the same time. To protect your data from duplicates, you should have a unique constraint/index on product_size(product_id, handbook_id).

SQL number of products

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

How to get distinct and lastest record with inner join query

I have two table named: customers and bill. customer and bill have one to many relation.
Customer table contains record of customer mobileNo,bikeNo etc
Bill table contain record of customer bill with bikeNo(foreign key),billdate etc.
I have query for that:
SELECT customer.mobileNo, bill.iDate AS Expr1
FROM (customer INNER JOIN
bill ON customer.bikeNo = bill.bikeNo)
ORDER BY bill.iDate;
Now How i get distinct and latest billdate record and mobileNo with this query?
Use GROUP BY and MAX():
SELECT customer.mobileNo, MAX(bill.iDate) AS iDate
FROM (customer INNER JOIN
bill ON customer.bikeNo = bill.bikeNo)
GROUP BY customer.mobileNo
ORDER BY iDate