Using the SUM function in SQLITE - sql

I have this basic sqlite3 database. In my store table, I am focused on the numberOfItems category. e.g., in my PurchaseToStore table, 4 different stores buy tacos with the number of them (numberOfItems) of 5, 55, 55, 55. What I want to do is calculate the sum of those values. So (55 + 55 + 55 + 5) = 170.
CREATE TABLE Store(
storeName VARCHAR(30),
storeid INTEGER,
PRIMARY KEY(storeid)
);
CREATE TABLE item(
itemName VARCHAR(30) ,
itemId INTEGER,
PRIMARY KEY(itemId)
);
CREATE TABLE PurchasedToStore(
storeid INTEGER,
itemId INTEGER,
numberOfItems INTEGER,
expirationMonth Integer,
PRIMARY KEY(storeid, itemID),
FOREIGN KEY(storeid) REFERENCES STORE(storeid),
FOREIGN KEY(itemid) REFERENCES item(itemid)
);
INSERT INTO Store Store('Meijer', 1);
INSERT INTO Store VALUES('Kroger', 2);
INSERT INTO Store VALUES('Walmart', 3);
INSERT INTO Store VALUES('Kmart', 4);
INSERT INTO item VALUES('taco', 556);
INSERT INTO item VALUES('burrito', 557);
INSERT INTO item VALUES('cheese', 600);
INSERT INTO STORE VALUES(1, 556, 5, 12);
INSERT INTO STORE VALUES(2, 556, 55, 11);
INSERT INTO STORE VALUES(3, 556, 55, 10);
INSERT INTO STORE VALUES(4, 556, 55, 2);
Here is what I have to try to do this:
SELECT sum(numberOfItems)
FROM item join purchasetostore
WHERE storeid = itemid;

It's a bit unclear what the end goal is, but a slight change to your where condition will get your desired sum. You'll want to match up itemid from the two tables;
SELECT sum(numberOfItems)
FROM item join PurchasedToStore
WHERE item.itemid = PurchasedToStore.itemid;
A probably slightly more useful query could include the item name of the items, and sum per name;
SELECT item.itemname, sum(numberOfItems)
FROM item join PurchasedToStore
WHERE item.itemid = PurchasedToStore.itemid
GROUP BY item.itemname;
A simple SQLfiddle with both queries.

Related

Update multiple tables in trigger where one of the tables is used for trigger activation

Let's say I have two tables called widgetCustomer and widgetSale. On an insert in widgetSale I want to add a timestamp to the widgetSale row and add the sale id as last_order_id to the widgetCustomer table.
I understand using AFTER INSERT ON will result in an error on trying to update the NEW row, hence we need to use BEFORE INSERT ON clause. Which brings forward a new issue that AUTO_INCREMENT has not yet generated a id for sale hence last_order_id would all be zero. There is a method to do this at MySQL/MariaDB TRIGGER but it seems to fail on my system (i.e., the last order ids are still zero).
As a work around I'm using two different triggers one before insert and one after insert. Although it does work I'm keen to learn if there is a possible flaws with the method above and is there a better way of doing this (both in terms of performance and data integrity).
My code is given below:
DROP TABLE IF EXISTS widgetSale;
DROP TABLE IF EXISTS widgetCustomer;
DROP TABLE IF EXISTS widgetLog;
CREATE TABLE widgetCustomer ( id integer primary key AUTO_INCREMENT, name TEXT, last_order_id INT, stamp TEXT );
CREATE TABLE widgetSale ( id integer primary key AUTO_INCREMENT, item_id INT, customer_id INTEGER, quan INT, price INT, stamp TEXT );
CREATE TABLE widgetLog ( id integer primary key AUTO_INCREMENT, stamp TEXT, event TEXT, username TEXT, tablename TEXT, table_id INT);
INSERT INTO widgetCustomer (name) VALUES ('Bob');
INSERT INTO widgetCustomer (name) VALUES ('Sally');
INSERT INTO widgetCustomer (name) VALUES ('Fred');
SELECT * FROM widgetCustomer;
CREATE TRIGGER stampSale BEFORE INSERT ON widgetSale
FOR EACH ROW BEGIN
SET NEW.stamp = CURRENT_TIMESTAMP();
END
CREATE TRIGGER stampOnRest AFTER INSERT ON widgetSale
FOR EACH ROW BEGIN
UPDATE widgetCustomer SET last_order_id = NEW.id, stamp = CURRENT_TIMESTAMP()
WHERE widgetCustomer.id = NEW.customer_id;
INSERT INTO widgetLog (stamp, event, username, tablename, table_id)
VALUES (CURRENT_TIMESTAMP(), 'INSERT', 'TRIGGER', 'widgetSale', NEW.id);
END
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (1, 3, 5, 1995);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (2, 2, 3, 1495);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (3, 1, 1, 2995);
SELECT * FROM widgetSale;
SELECT * FROM widgetCustomer;
SELECT * FROM widgetLog;
I'm using mariadb 10.6.* on Archlinux.

SQL Data Manipulation (Adding FK and Displaying one Data from different table)

I'm new in SQL and we have an activity. I only have two problems in my query, first is adding the FK because when I run it, this will have an error that show like this: near "FOREIGN": syntax error and I don't know why.
Second is I dont know how to display the Products, Vendor ID and Name that comes from different table (This is the part of the instruction:
Determine which products have a quantity of less than 1000 then display the products Vendor ID and Name)
CREATE TABLE Products (ProductID int NOT NULL PRIMARY KEY, Description varchar (100), Quantity
int, Price int (50), VendorID int NOT NULL);
CREATE TABLE Vendors (VendorID int NOT NULL PRIMARY KEY, Name varchar (50), ContactNum int);
ALTER TABLE Products ADD FOREIGN KEY (VendorID) REFERENCES Vendors (VendorID);
INSERT INTO Vendors VALUES ('V00001', 'Universal Corporation','8633-76131');
INSERT INTO Vendors VALUES('V00002', 'Liwayway Corporation','8844-8441');
INSERT INTO Vendors VALUES ('V00003', 'Monde Nissin', '7759-5000');
Select * FROM Vendors;
INSERT INTO Products VALUES ('P000101', 'Jack N Jill Piattos', 1000, 15, 'V00001');
INSERT INTO Products VALUES ('P000102', 'Jack N Jill Nova', 1000, 15, 'V00001');
INSERT INTO Products VALUES ('P000105', 'Oishi Prawn Crackers', 700, 8, 'V00002');
INSERT INTO Products VALUES ('P000107', 'Nissin Eggnog Cookies', 850, 7, 'V00003');
SELECT * FROM Products;
UPDATE Products SET Quantity = Quantity + 274 WHERE ProductID = 'P000101';
UPDATE Products SET Quantity = Quantity - 42 WHERE ProductID = 'P000107';
SELECT * FROM Products;
SELECT DISTINCT ProductID, Description, Quantity FROM Products WHERE Quantity < 1000;

How do I create an SQLite trigger on a table based on data in other tables?

I have two tables -
part(partID, brand, price, size)
consists_of(customerID, partID, quantity, price, shipdate)
|
FK part.ID from part
Table part is never going to be changed/updated, but consists_of will be.
How do I add a [before insert?] trigger on consists_of that checks if consists_of.price for each entry is less than or equal consists_of.quantity * part.price for that particular consists_of.partID and raises an abort if it isn't so?
Or,
How do I add [after insert?] trigger on consists_of that does INSERT INTO consists_of(price) VALUES (...) where the value of consists_of.price is equal to consists_of.quantity * part.price for that consists_of.partID?
If I understand you correctly, you can select part.price in subqueries and calculate part.price * consists_of.quantitiy.
before insert
CREATE TABLE part(part_id INTEGER, price INTEGER);
CREATE TABLE consists_of(customer_id INTEGER, part_id INTEGER, quantity INTEGER, price INTEGER);
INSERT INTO part VALUES(10, 50);
INSERT INTO part VALUES (20, 1000);
CREATE TRIGGER IF NOT EXISTS raise_if_consists_of_price_too_expensive
AFTER INSERT ON consists_of
WHEN new.price > (SELECT part.price * new.quantity FROM part WHERE part.part_id = new.part_id)
BEGIN
SELECT RAISE (ABORT, 'too expensive.');
END;
-- OK
INSERT INTO consists_of(customer_id, part_id, quantity, price)
VALUES(10050, 20, 31, 100);
-- OK
INSERT INTO consists_of(customer_id, part_id, quantity, price)
VALUES(80030, 10, 9, 50 * 9);
-- Raise abort
INSERT INTO consists_of(customer_id, part_id, quantity, price)
VALUES(80099, 10, 9, 50 * 9 + 1);
after insert
CREATE TABLE part(part_id INTEGER, price INTEGER);
CREATE TABLE consists_of(customer_id INTEGER, part_id INTEGER, quantity INTEGER, price INTEGER);
INSERT INTO part VALUES(10, 50);
INSERT INTO part VALUES (20, 1000);
CREATE TRIGGER IF NOT EXISTS fill_consists_of_price
AFTER INSERT ON consists_of
BEGIN
UPDATE consists_of
SET
price = (
SELECT consists_of.quantity * part.price
FROM part
WHERE part.part_id = consists_of.part_id
)
WHERE customer_id = new.customer_id AND part_id = new.part_id
;
END;
INSERT INTO consists_of(customer_id, part_id ,quantity)
VALUES(10050, 20, 31);
INSERT INTO consists_of(customer_id, part_id ,quantity)
VALUES(80033, 10, 9);

How to update a column based on matching ID's

I create two tables housing_listing and buyer. How to update the value of sold in housing_listing table to TRUE if the id (transaction_id) of housing_listing matches the id (transaction_id) of buyer?
Creating tables:
CREATE TABLE housing_listing (
transaction_id INT PRIMARY KEY,
number_of_bedrooms INT,
number_of_bathrooms INT,
listing_price INT,
listing_agent TEXT,
agent_email TEXT,
listing_office TEXT,
date_of_listing DATETIME,
zip_code INT,
sold BOOL,
Commission INT
);
CREATE TABLE buyer (
transaction_id INT PRIMARY KEY,
buyer_name TEXT,
buyer_id INT,
sale_price INT,
date_of_sale DATETIME,
selling_agent TEXT
)
Inserting data to buyer table:
INSERT INTO buyer VALUES (1, "Ania Kraszka", 1, 2000000,'2020/02/27','FADU');
INSERT INTO buyer VALUES (2, "Ania Kraszka", 2, 2000000,'2011/02/27','FADU');
Inserting data to housing_listing table:
INSERT INTO housing_listing VALUES (1, 3, 2, 2000000, 'Liza','liza#uba.ar', 'UBA','2018/02/27',45049, 'FALSE',0);
INSERT INTO housing_listing VALUES (2, 2, 1, 3000, 'Tom','tom#utn.ar', 'UTN','2011/02/27',45049,'FALSE',0);
INSERT INTO housing_listing VALUES (9, 1, 1, 40000, 'Tom','tom#fadu.ar', 'FADU','2011/02/27',45049, 'FALSE',0);
You can use a correlated subquery:
update housing_listing
set sold = true
where exists (select 1
from buyer b
where b.transaction_id = housing_listing.transaction_id
);
I assume you mean that the transaction ids match.
You can do something like this-
UPDATE housing_listing
SET sold = 'TRUE'
WHERE transaction_id IN (SELECT transaction_id FROM buyer);
SELECT * FROM housing_listing;
1|3|2|2000000|Liza|liza#uba.ar|UBA|2018/02/27|45049|TRUE|0
2|2|1|3000|Tom|tom#utn.ar|UTN|2011/02/27|45049|TRUE|0
9|1|1|40000|Tom|tom#fadu.ar|FADU|2011/02/27|45049|FALSE|0

SQL Query problems exist

I'm having a lot of troubles with the last query I need and I think it's a level out of my league so any help is appreciated.
The tables:
CREATE TABLE Recipe
(
nrecipe integer,
name varchar(255),
primary key (nrecipe)
);
CREATE TABLE Food
(
designation varchar(255) unique,
quantity integer,
primary key (designation)
);
CREATE TABLE Contains
(
nrecipe integer,
designation varchar(255),
quantity integer,
primary key (nrecipe, designation),
foreign key (nrecipe) references Recepie (nrecipe),
foreign key (designation) references Food (designation)
);
Quantity in Food table is the quantity stored in warehouse.
Quantity in Contains is the amount needed of a food element to use in recipe.
Quantity in Food table and Contains differ from each other.
The query:
I want to know the names of ALL recipes that are possible to be done with the food stored in warehouse.
It requires that the quantity of every element of food in warehouse is bigger than the quantity needed for the recipe.
EDIT: also, it shouldn't show a recipe's name if there is nothing referring to it on Contains table.
To make it easier to understand, I'll give some data:
INSERT INTO Recipe VALUES ('01', 'Steak with potatos and water');
INSERT INTO Recipe VALUES ('02', 'Rice and ice tea');
INSERT INTO Recipe VALUES ('03', 'Potatos and shrimp');
INSERT INTO Recipe VALUES ('04', 'Water');
INSERT INTO Recipe VALUES ('05', 'Steak with rice');
INSERT INTO Recipe VALUES ('06', 'Steak with spaguetti');
INSERT INTO Recipe VALUES ('07', 'Potatos with rice');
INSERT INTO Food VALUES ('Water', 5);
INSERT INTO Food VALUES ('Ice tea', 10);
INSERT INTO Food VALUES ('Steak', 30);
INSERT INTO Food VALUES ('Potatos', 20);
INSERT INTO Food VALUES ('Rice', 50);
INSERT INTO Food VALUES ('Shrimp', 5);
INSERT INTO Food VALUES ('Spaguetti', 5);
INSERT INTO Contains VALUES ('01', 'Steak', 1);
INSERT INTO Contains VALUES ('01', 'Potatos', 15);
INSERT INTO Contains VALUES ('01', 'Water', 10);
INSERT INTO Contains VALUES ('02', 'Rice', 5);
INSERT INTO Contains VALUES ('02', 'Ice tea', 8);
INSERT INTO Contains VALUES ('03', 'Potatos', 1);
INSERT INTO Contains VALUES ('03', 'Shrimp', 10);
INSERT INTO Contains VALUES ('04', 'Water', 20);
INSERT INTO Contains VALUES ('05', 'Steak', 1);
INSERT INTO Contains VALUES ('05', 'Rice', 20);
INSERT INTO Contains VALUES ('06', 'Steak', 1);
INSERT INTO Contains VALUES ('06', 'Spaguetti', 10);
The outcome expected from the query is:
Rice and ice tea
Steak with rice
Since it's the only two recipes with enough quantity in warehouse.
EDIT: potatoes with rice shouldn't appear as it is a recipe but isn't in contains list
Thanks for input and time. Any help is welcome :)
I'd use >= ALL operator :
SELECT name
FROM Recipe R
WHERE 0 >= ALL (SELECT C.quantity - F.quantity
FROM Food F
INNER JOIN Contains C
USING (designation)
WHERE C.nrecipe = R.nrecipe);
The correct spelling is recipe, and you used different names for some columns (recepie, nrecipe, nrecepie) so I changed it. Note that instead of using a varchar primary key, you should use a numeric one.
Edit:
SELECT name
FROM Recipe R
WHERE 0 >= ALL (SELECT C.quantity - F.quantity
FROM Food F
INNER JOIN Contains C
USING (designation)
WHERE C.nrecipe = R.nrecipe)
AND EXISTS(SELECT NULL
FROM Contains C
WHERE C.nrecipe = R.nrecipe);
This is in SQL Server because that is what I have:
select
r.name
from
Recepie r
where
not exists
(
select 1
from
[Contains] c
where
c.nrecipe = r.nrecepie and
not exists
(
select 1
from
Food f
where
f.designation = c.designation and
f.quantity >= c.quantity
)
)
Which in plain language is "Get me all recipes where there are no ingredients of insufficient quantity"