I have a mysql query that needs to return the supplier ID from the supplier table by searching with the supplier name but it keeps returning multiple values.
CREATE DEFINER=`root`#`%` PROCEDURE `sp_insert_sup_order`(
supname varchar(50),
dat date,
total decimal(10,2)
)
BEGIN
insert into Supplier_Order
(
Supplier_ID,
SupDate,
Total,
Sup_Name
)
values
(
(select Supplier_ID from Supplier Where Supplier_ID.SupName = supname ),
dat,
total,
supname
);
Thats the query. Any help with this will be appreciated thanks
(select Supplier_ID from Supplier Where Supplier_ID.SupName = supname )
this should be like this:
(select Supplier_ID from Supplier Where Supplier.SupName = supname ),
And why do you store the supplier name and the id in the order ? that should not be done, image you have to change the name of the supplier, you will have to update all orders. Only the supplier id should be stored in the order table!
Related
CREATE TABLE Products (
Product Name varchar(30),
Unit Price int
)
INSERT INTO Products VALUES
('soap', 40),
('brushteeth', 30)
Try this:
SELECT ProductName FROM Products
WHERE UnitPrice = (SELECT max(UnitPrice) FROM Products)
SELECT ProductName
FROM Products
WHERE UnitPrice = (
SELECT MAX(UnitPrice)
FROM Products
)
This should work. However, I'm pretty sure there is a more optimized way to do that.
Let's say I have 2 tables A and B.
These 2 tables have 3 columns in common Name, Id and Price.
This is the query I used for 1 table :
SELECT Name, Id, Price FROM A WHERE Id = "123" and Price = (SELECT MIN(Price) FROM A);
I've just realised that this query doesn't work when the lowest price is held by another Id.
So I've look around and I think I should use GROUP BY ?
I've changed it to :
SELECT Name, MIN(Price) FROM A WHERE Id = "123" GROUP BY Name;
But this is not the expected result.
Let's say in table A I have :
Name
Id
Price
Au
123
12
Be
123
16
St
122
9
Ge
123
10
And for table B I have :
Name
Id
Price
La
123
14.5
La
123
12
St
123
13
Is
123
12
Is
123
10
La
123
10
Is
123
10
And the expected result is :
Name
Price
Ge
10
Is
10
La
10
The expected result is 1 row long because in the set of data there is only one row that match the condition but if I had another row with a Price of 10 and an Id of 123 it should be there also. So if there are more rows that matched the condition I want them in the result.
The problem is that when I do the following query using UNION I don't know how to get the lowest price for a specific Id:
SELECT Name, Id, Price FROM A UNION SELECT Name, Id, Price FROM B;
So what can I add to my query to have the expected result and then how would it work if I use union to get the lowest price of a specific Id over 2 tables ?
On MySQL 8+, we can use RANK here with a union query:
WITH cte AS (
SELECT Name, Id, Price FROM A WHERE Id = '123'
UNION ALL
SELECT Name, Id, Price FROM B WHERE Id = '123'
),
cte2 AS (
SELECT *, RANK() OVER (ORDER BY price) rnk
FROM cte
)
SELECT Name, Id, Price
FROM cte2
WHERE rnk = 1;
Here is a query which should work on earlier versions of MySQL:
SELECT Name, Id, Price
FROM
(
SELECT Name, Id, Price FROM A WHERE Id = '123'
UNION ALL
SELECT Name, Id, Price FROM B WHERE Id = '123'
) t
WHERE Price = (
SELECT Price FROM A WHERE Id = '123'
UNION ALL
SELECT Price FROM B WHERE Id = '123'
ORDER BY Price
LIMIT 1
);
This should be ok for you:
select *
from (select Name, id, Price FROM A
union
select Name, id, Price FROM B) Tab
where (Tab.id, Tab.price) = (select Tab2.id, min(Tab2.price)
from (select Name, id, Price FROM A
union
select Name, id, Price FROM B) Tab2
where Tab2.id = '123')
You have only one place where you put the ID you are looking for.
Here you can see the demo:
DEMO
/*This returns everything from your two tables*/
select *
from (SELECT Name, id, Price FROM A
union
select Name, id, Price FROM B) Tab
/*this returns the minimal price for your requested ID, here you requested id =123*/
select Tab2.id, min(Tab2.price)
from (SELECT Name, id, Price FROM A
union
select Name, id, Price FROM B) Tab2
where Tab2.id = '123'
--with this where clause:
where (Tab.id, Tab.price)
/*you are telling the query :
give me every row from all the data(first query)that has
this combination of ID + PRICE:
123 + 10 (you have found this with the second query)
So, you do not care what name it is, it only has to have :
ID = 123 and the lowest price which is 10.
ID 123 was requested from you and lowest price for that ID is 10,
which you have founded with the second query.*/
I tested this on db-fiddle.com and it returns all the rows with the lowest price:
SELECT Id, Name, Price
FROM (SELECT * FROM A UNION SELECT * FROM B) TMP
WHERE (Price, Id) = (
SELECT MIN(Price), Id
FROM (SELECT * FROM A UNION SELECT * FROM B) TMP2
WHERE Id = "123"
);
Here are the script for the tables I tested the query against:
create table A(
_id INT NOT NULL AUTO_INCREMENT,
Id VARCHAR(100) NOT NULL,
Name VARCHAR(100) NOT NULL,
Price INT NOT NULL,
PRIMARY KEY ( _id )
);
create table B(
_id INT NOT NULL AUTO_INCREMENT,
Id VARCHAR(100) NOT NULL,
Name VARCHAR(100) NOT NULL,
Price INT NOT NULL,
PRIMARY KEY ( _id )
);
INSERT INTO A(Id, Name, Price)
VALUES
('123', 'Name123a1', 21),
('123', 'Name123a2', 41),
('124', 'Name124a', 40);
INSERT INTO B(Id, Name, Price)
VALUES
('123', 'Name123b1', 22),
('123', 'Name123b2', 21),
('124', 'Name124b', 20);
The solution took some time to figure out, because I am rusty. Thanks to VBoka that helped me with sorting out bugs.
I would do this after your last query, the one that outputs 3 price values and you need the minimum.
create a cte
create a rank using ROW_NUMBER based on price in ASC order which is the default order if you want highest then add DESC in the end
filter the data with that rank column
with data as (
select
*, ROW_NUMBER () OVER(ORDER BY price ) as rank_ from table
)
select * from data where rank_ = 1
I have a database called Real_Estate_Lab_Project, I have a table call listings, with a column named listing price.
listing_key int PK
listing_status int
listing_type int
date_listed date
date_expires date
date_unlisted date
reason_unlisted int
address varchar(50)
city varchar(30)
state char(2)
zip_code varchar(10)
lot_number varchar(50)
residential_area int
listing_price int
listing_agreement_signed_date date
remark varchar(1000)
I am trying to run
USE Real_Estate_Lab_Project;
SELECT count(*)
as no_of_listings,
avg(price) as avg_listing_price, sum(listings)
as sum_of_listings, min(price)
as min_price, max(price)
as max_price
from Listing
where status = 'Active'
When I run script it is telling me
Error Code: 1146. Table 'real_estate_lab_project.listing' doesn't exist 0.000 sec, but I know it exists as I can see it when I do
SELECT * from listings.
The date expires column does have some that are expired, but some are not.
What am I missing?
it looks you have to replace 'Listing' with listings in your sql
SELECT count(*)
as no_of_listings,
avg(price) as avg_listing_price, sum(listings)
as sum_of_listings, min(price)
as min_price, max(price)
as max_price
from listings
where status = 'Active
'
I have three tables invoice_lineItem, contract_Details and Tranche.
What I want to achieve is to get total purchase price of contracts based on contractID from invoice_lineItem and contract_Details and then get TotalPurchasePrice of all contract in the same tranche.
Here's the fiddle http://sqlfiddle.com/#!9/67123/1 of what I've tried
I get purchase price of contractID of other tranche added to
trancheID 1 as shown below
create table invoice_lineItem(
inv_id INT NOT NULL AUTO_INCREMENT ,
contractID VARCHAR(255),
purchasePrice INT,
PRIMARY KEY(inv_id)
);
create table contract_details(
contractID VARCHAR(255) NOT NULL,
funder VARCHAR(255),
PRIMARY KEY(contractID)
);
create table tranche_details(
contractID VARCHAR(255) NOT NULL,
trancheID VARCHAR(255),
PRIMARY KEY(contractID)
);
insert into invoice_lineItem(contractID,purchasePrice) VALUES ('1/14S/03',5);
insert into invoice_lineItem(contractID,purchasePrice) VALUES ('1/14S/03',5);
insert into invoice_lineItem(contractID,purchasePrice) VALUES ('2/14S/03',15);
insert into invoice_lineItem(contractID,purchasePrice) VALUES ('2/14S/03',15);
insert into invoice_lineItem(contractID,purchasePrice) VALUES ('3/14S/03',5);
insert into contract_details(contractID,funder) VALUES ('1/14S/03','ABC');
insert into contract_details(contractID,funder) VALUES ('2/14S/03','ABC');
insert into contract_details(contractID,funder) VALUES ('3/14S/03','ABC');
insert into tranche_details(contractID,trancheID) VALUES ('1/14S/03',1);
insert into tranche_details(contractID,trancheID) VALUES ('2/14S/03',1);
insert into tranche_details(contractID,trancheID) VALUES ('3/14S/03',2);
SELECT cd.contractID,SUM(inv.purchasePrice) as totalPP
FROM `contract_details` cd INNER JOIN invoice_lineitem inv ON inv.contractID=cd.contractID
WHERE cd.funder='ABC'
What i want to achieve is to get
totalPurchasePrice For All Contracts with same contractID and the
funder Name 'ABC' from ContractDetails
inv_id:1
contractID:1/14S/03
PurchasePrice:5
inv_id:2
contractID:1/14S/03
PurchasePrice:5
So total PurchasePrice is: 10 and similarly for 2/14S/03 it will be 30 and now since contractID:1/14S/03 and contractID:2/14S/03 are in same tranche I want to SUM their totalPurchase Price
SELECT cd.contractID,SUM(inv.purchasePrice) as totalPP FROM `contract_details` cd
INNER JOIN invoice_lineitem inv ON inv.contractID=cd.contractID
INNER JOIN tranche_details td ON td.trancheID=(SELECT trancheID FROM tranche_details GROUP by trancheID having COUNT(*)>1)
WHERE cd.funder='ABC' GROUP BY cd.contractID
Edit:
Here i found Solution DEMO http://sqlfiddle.com/#!9/69ee8/10
select td.trancheID,GROUP_CONCAT(td.contractID SEPARATOR ';') as allcontract,SUM(s.totalPP) as totalPPtranche
from tranche_details td
left join
(
SELECT cd.contractID,cd.funder,SUM(inv.purchasePrice) as totalPP FROM `contract_details` cd
INNER JOIN invoice_lineitem inv ON inv.contractID=cd.contractID
WHERE cd.funder='ABC' GROUP BY cd.contractID
) s
on td.contractID = s.contractID
WHERE s.funder='ABC'
GROUP BY (td.trancheID)
I have a query
SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid = 'broker'
AND
cancelled is null
GROUP BY product
WITH ROLLUP
Is it possible to query a table to get a brokers id and then for each broker run the query above written as 1 query?
Almost like:
SELECT brid FROM membership
THEN
SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid = membership.brid
AND
cancelled is null
GROUP BY product
WITH ROLLUP
THEN
SELECT NEXT brid
Is this possible? i know how to do it in PHP but i would prefer 1 query that can create an array rather than tons of queries for each.
Thanks
Adam.
Sure, you can GROUP BY both the 'brid' field and the 'product' field. As noted below, WITH ROLLUP will cause it to sort by 'brid' and then by 'product':
SELECT
brid,
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid IN (SELECT brid FROM membership)
AND
cancelled is null
GROUP BY brid, product
WITH ROLLUP
SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
INNER JOIN membership on membership.brid = products.brid
WHERE
cancelled is null
GROUP BY product
WITH ROLLUP
As far as I can understand from your example, all you need is inner join between membership and products on brid
Take the following example:
products table:
CREATE TABLE `test` (
`price` int(11) DEFAULT NULL,
`product` varchar(20) DEFAULT NULL,
`brid` varchar(20) DEFAULT NULL,
`cancelled` varchar(20) DEFAULT NULL
)
membership table:
CREATE TABLE `membership` (
`brid` varchar(20) DEFAULT NULL
)
And following is my query as you required:
SELECT
t.brid, count(t.product) as amount,
t.product,
sum(t.price) AS price
FROM products t, membership m
WHERE
t.brid = m.`brid`
AND
cancelled is null
GROUP BY product
Hope that helps!