I've been stuck on a MySQL query. The table is:
CREATE TABLE items_costs (
UPC varchar(15) NOT NULL,
SupplierID int(11) NOT NULL,
Current_as_of_Date datetime DEFAULT NULL,
Cost1 float DEFAULT NULL,
Cost2 float DEFAULT NULL,
Cost3 float DEFAULT NULL,
MSRP float DEFAULT NULL,
MAP float DEFAULT NULL,
Unique_Entry_Id datetime DEFAULT NULL,
PRIMARY KEY (UPC,SupplierID),
KEY SupplierID (SupplierID),
CONSTRAINT items_costs_ibfk_1 FOREIGN KEY (UPC) REFERENCES items (UPC),
CONSTRAINT items_costs_ibfk_2 FOREIGN KEY (SupplierID) REFERENCES suppliers (SupplierID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8`
I'm getting the lowest of Cost1, Cost2, Cost3 for each item:
MIN(LEAST(IFNULL(ic.Cost3, ic.Cost1), IFNULL(ic.Cost2, ic.Cost1), ic.Cost1)) AS Cost
However, now I need to get the SupplierID associated with that particular Cost
I've tried:
SELECT
ic.UPC,
ic.SupplierID,
ic.Current_as_of_Date,
ic.Cost1 AS Cost,
ic.MSRP,
ic.MAP,
s.SupplierName,
s.Map_YN AS Supplier_MAP
FROM
items_costs AS ic
JOIN
suppliers AS s ON s.supplierId = ic.SupplierID
WHERE
(ic.upc , ic.Cost1) IN (SELECT
ic_min.UPC,
MIN(LEAST(IFNULL(ic_min.Cost3, ic_min.Cost1),
IFNULL(ic_min.Cost2, ic_min.Cost1),
ic_min.Cost1)) AS Cost
FROM
items_costs ic_min
GROUP BY ic_min.UPC))
...which gives the lowest Cost by UPC, as recommended in other threads. However, still getting duplicate UPC's, which should be unique.
What could I be doing wrong here?
Thanks a lot!
You could use DISTINCT
SELECT DISTINCT
ic.UPC,
ic.SupplierID,
ic.Current_as_of_Date,
ic.Cost1 AS Cost,
ic.MSRP,
ic.MAP,
s.SupplierName,
s.Map_YN AS Supplier_MAP
FROM items_costs AS ic
JOIN suppliers AS s ON s.supplierId = ic.SupplierID
WHERE (ic.upc , ic.Cost1) IN (
SELECT
ic_min.UPC,
MIN(LEAST(IFNULL(ic_min.Cost3, ic_min.Cost1),
IFNULL(ic_min.Cost2, ic_min.Cost1),
ic_min.Cost1)) AS Cost
FROM items_costs ic_min
GROUP BY ic_min.UPC))
Thanks for your help!
I found the answer here, and it seems to be a common question: https://dev.mysql.com/doc/refman/5.6/en/example-maximum-column-group-row.html
SELECT
ic1.upc,
ic1.supplierid,
ic1.MSRP,
ic1.MAP,
ROUND((LEAST(IFNULL(ic1.Cost3, ic1.Cost1),
IFNULL(ic1.Cost2, ic1.Cost1),
ic1.Cost1)),
2) AS Cost,
s.SupplierName,
s.Map_YN AS Supplier_MAP
FROM
items_costs AS ic1
JOIN
suppliers AS s ON s.supplierid = ic1.supplierid
WHERE
ic1.cost1 = (SELECT
MIN(ic2.cost1)
FROM
items_costs AS ic2
WHERE
ic1.upc = ic2.upc)
Related
I created two tables using MYSQL, tblorder and tblitem.
CREATE TABLE `tblorder` (
`orderId` int NOT NULL,
`orderName` varchar(45) NOT NULL,
PRIMARY KEY (`orderId`)
CREATE TABLE `tblitem` (
`itemId` int NOT NULL,
`itemName` varchar(45) NOT NULL,
`itemUnit` varchar(5) NOT NULL,
`itemRate` double NOT NULL,
`orderRef` int NOT NULL,
PRIMARY KEY (`itemId`),
KEY `fk1_idx` (`orderRef`),
CONSTRAINT `fk1` FOREIGN KEY (`orderRef`) REFERENCES `tblorder` (`orderId`)
I tried to join the two tables using query below
SELECT orderId,orderName, itemName, itemUnit,itemRate
FROM tblitem
INNER JOIN tblorder on tblorder.orderId = tblitem.orderRef
Now result show like Image-01
How to remove duplicate values in orderId ,OrderName columns in result table?
Thanks to help me to solve this problem.
After joining tables is it possible to get output like below?
Answer for this question is available in below link. https://dba.stackexchange.com/questions/287746/join-two-tables-in-mysql-and-avoid-duplicate-values
SELECT CASE WHEN sortId = 1 THEN CAST(orderId AS CHAR(10)) ELSE '' END AS
orderId, CASE WHEN sortId = 1 THEN orderName ELSE '' END AS orderName,
itemName, itemUnit, itemRate
FROM
(
SELECT orderId, orderName, itemName, itemUnit, itemRate, ROW_NUMBER() OVER
(PARTITION BY orderId ORDER BY itemId) AS sortId
FROM
(
SELECT orderId, orderName, itemName, itemUnit, itemRate, itemId
FROM tblitem
INNER JOIN tblorder
on tblorder.orderId = tblitem.orderRef
) orderItems
) orderItemsSorted
ORDER BY orderItemsSorted.orderId, orderItemsSorted.sortId
I have two tables, publishers and titles.
I want to find out how many types of each book the publisher has, such as history, childrens, etc.
Here are the two tables:
CREATE TABLE publishers
(
pub_id CHAR(3) NOT NULL,
pub_name VARCHAR(20) NOT NULL,
city VARCHAR(15) NOT NULL,
state CHAR(2) ,
country VARCHAR(15) NOT NULL,
CONSTRAINT pk_publishers PRIMARY KEY (pub_id)
)ENGINE = InnoDB;
CREATE TABLE titles
(
title_id CHAR(3) NOT NULL,
title_name VARCHAR(40) NOT NULL,
type VARCHAR(10) ,
pub_id CHAR(3) NOT NULL,
pages INTEGER ,
price DECIMAL(5,2) ,
sales INTEGER ,
pubdate DATE ,
contract SMALLINT NOT NULL,
CONSTRAINT pk_titles PRIMARY KEY (title_id)
)ENGINE = InnoDB;
All I have been able to do so far is find out the total count of types(genres) of books.
SELECT COUNT(DISTINCT type)
FROM publishers AS a
INNER JOIN titles AS p
ON a.pub_id = p.pub_id;
How can I go about doing this?
You need to have a query with Group By as shown below
SELECT a.pub_id, a.pub_name, p.type, COUNT(DISTINCT p.type)
FROM publishers AS a
INNER JOIN titles AS p ON a.pub_id = p.pub_id
GROUP BY a.pub_id, a.pub_name, p.type
add group by for pub_id and pub_name to avoid two publishers having same name to be considered as one publisher
Try this out: http://sqlfiddle.com/#!9/9331e/24
SELECT p.pub_name, t.type, count(t.type)
FROM publishers AS p
INNER JOIN titles AS t on t.pub_id = p.pub_id
GROUP BY p.pub_id, t.type
I have two tables: attendees & history. History table is where I post payments for all the attendees. It also stores an historyid and the attendeeid. The query I'm using to try to get to the last record entered in the history table for a particular attendee is:
$stmt = $db->prepare('SELECT a.fname, a.lname, h.amount, h.subsidy, h.last_payment, h.balance
FROM history AS h
INNER JOIN
attendees AS a
ON a.attendeeid = h.attendeeid
WHERE a.attendeeid = :id
ORDER BY historyid DESC LIMIT 1)');
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll();
But the code is failing to return anything at all. Since there will likely be historyid's greater than the one I'm trying to retrieve, how do I associate the greatest historyid for that attendee so I get the last record entered for them in the History table? What I'm using is obviously not the answer. Thanks in advance for your help.
Sorry. The schemas are:
TABLE attendees (
attendeeid int(10) unsigned NOT NULL AUTO_INCREMENT,
fname varchar(20) NOT NULL,
lname varchar(20) NOT NULL,
dojid varchar(10) NOT NULL,
address1 varchar(25) NOT NULL,
address2 varchar(25) NOT NULL,
city varchar(20) NOT NULL,
state char(2) NOT NULL,
zipcode varchar(5) NOT NULL,
phonenumber varchar(15) NOT NULL,
memberid int(10) unsigned NOT NULL,
PRIMARY KEY (attendeeid),
KEY memberid (memberid),
CONSTRAINT attendees_ibfk_2 FOREIGN KEY (memberid) REFERENCES members (memberid) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
TABLE history (
historyid int(10) unsigned NOT NULL AUTO_INCREMENT,
amount float NOT NULL,
subsidy char(1) NOT NULL,
last_payment date NOT NULL,
amount_paid float NOT NULL,
balance float NOT NULL,
attendeeid int(10) unsigned NOT NULL,
memberid int(10) unsigned NOT NULL,
PRIMARY KEY (historyid),
KEY attendeeid (attendeeid),
CONSTRAINT history_ibfk_2 FOREIGN KEY (attendeeid) REFERENCES attendees (attendeeid) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Please can you provide the structure of both tables? I'm guessing your tables contains a date columns, or something like that.
Anyway, I would try something like:
select *
from (select a.attendeeid,max(h.id)
FROM history AS h INNER JOIN attendees AS a ON a.attendeeid = h.attendeeid
group by a.attendeeid) as maxHistoryPerAttendee
In that way, you will have the maximun history id per each attendeeid. I'm guessing the max id, is the last inserted row.
This is your query with a couple fields added:
select *
from (select a.attendeeid,max(h.historyid),fname,lname,last_payment,amount
FROM history AS h INNER JOIN attendees AS a ON a.attendeeid = h.attendeeid
group by a.attendeeid) as maxHistoryPerAttendee
where attendeeid = 29
In doing that, I got the first-row entry for that attendee's last_payment instead of the last_payment associated with the MAX(historyid) row.
To add to this and call it done, I got this to work. It's very near my original query.
$stmt = $db->prepare('SELECT fname, lname, amount, subsidy, last_payment, balance, a.attendeeid, h.historyid
FROM history AS h
INNER JOIN attendees AS a ON a.attendeeid = h.attendeeid
where h.attendeeid = :id
ORDER BY h.historyid DESC LIMIT 1');
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
Works like a champ!
I have the following tables.
CREATE TABLE `Customer` (
`CID` varchar(10) CHARACTER SET latin1 NOT NULL DEFAULT '',
`Name` varchar(40) CHARACTER SET latin1 NOT NULL DEFAULT '',
`City` varchar(40) CHARACTER SET latin1 NOT NULL DEFAULT '',
`State` varchar(40) CHARACTER SET latin1 NOT NULL DEFAULT '',
PRIMARY KEY (`CID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;
CREATE TABLE `LineItem` (
`LID` varchar(10) NOT NULL DEFAULT '',
`OID` varchar(10) NOT NULL DEFAULT '',
`PID` varchar(110) NOT NULL DEFAULT '',
`Number` int(11) DEFAULT NULL,
`TotalPrice` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`LID`),
KEY `Order ID` (`OID`),
CONSTRAINT `Order ID` FOREIGN KEY (`OID`) REFERENCES `OrderItem` (`OID`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `OrderItem` (
`OID` varchar(10) NOT NULL DEFAULT '',
`CID` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`OID`),
KEY `CID` (`CID`),
CONSTRAINT `CID` FOREIGN KEY (`CID`) REFERENCES `Customer` (`CID`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `Product` (
`PID` varchar(10) NOT NULL DEFAULT '',
`ProductName` varchar(40) DEFAULT '',
`Price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`PID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
What I've been trying to do in my query is run it so I can successfully get it to do the following:
List the products bought by all the customers of Newark
List the products ordered only by the customers of Newark
For #5, I tried this query:
Select product.productname
From Customer as c INNER JOIN OrderItem as o
ON c.CID = o.CID
INNER JOIN LineItem line
ON o.OID = line.OID
Inner Join Product product
ON line.PID = product.PID
Where C.City = 'Newark'
Having Count(product.productname) > 1;
But it only returns one value and it should return 2 (unless I am not using it properly).
For #6 I understand the concept but I don't know how to "subtract tables" in SQL.
The goal of the first question is to list the common items purchased by everyone from Newark. So if Person A bought Items X, Y and Z and Person B bought W, V, and Y, the query will return "Item Y".
I guess my comment is an answer.
Having Count(product.productname) > 1;
Having requires a group by to function correctly as it's a filter on an aggregate and aggregates require a group by. 90% of database engines would have returned an error explicitly stating it requires a group by...but MySQL prefers to do the wrong thing instead of return an error to you (it's why you got one row...MySQL did a group by of whatever it felt like). Add a group by (I assume on product name with what you have here) and it should work.
you need to add GROUP BY . Try this:
Select product.productname
From Customer as c
INNER JOIN OrderItem as o ON c.CID = o.CID
INNER JOIN LineItem line ON o.OID = line.OID
Inner Join Product product ON line.PID = product.PID
Where C.City = 'Newark'
Group by product.productname
Having Count(*) > 1;
Two other answers have pointed out that if you want the HAVING then you need a GROUP BY. But your question doesn't actually ask a question or explain what your query is supposed to return. (You are not explaining clearly in your question or comments.) You wrote a comment, "I have two people from Newark and was trying to show the item(s) [product(s)?] that both of them purchased." But if your query is only "corrected" with grouping then it calculates the wrong counts.
A problem is that you should return PID (and maybe ProductName). You need to list products. PIDs as key are presumably 1:1 with products but ProductName is not a key so product names are not 1:1 with products. ProductName can even be NULL. So selecting ProductName does not get you all the relevant products. (Also in LineItem PID should be a FOREIGN KEY.)
Another problem is that you should use PID to GROUP BY product. ProductName is not a key of Product. So two products can have the same name. So you will get the count for each product name, not for each product. Plus ProductName can be NULL. (Even if you were only returning the names not PIDs of products with those counts, you would need to group by PID.)
Another problem is the counts are wrong. Grouping by PID groups rows that can be made by combining a Newark Customer row, an OrderItem row and a LineItem row for a product. Those combination rows are counted by COUNT(PID). But you want the number of disinct Newark customers in those rows. You could do this by a sub-select but there happens to be a shorter way.
SELECT p.PID, p.ProductName
FROM Customer c
JOIN OrderItem AS o ON c.CID = o.CID
JOIN LineItem l ON o.OID = l.OID
JOIN Product p ON l.PID = p.PID
WHERE c.City = 'Newark'
GROUP BY (p.PID)
HAVING COUNT(DISTINCT c.CID) > 1;
You get a query for goal 1 after a change in part of its condition.
HAVING COUNT(DISTINCT c.CID)
= (SELECT COUNT(*) FROM Customer WHERE City='Newark')
Relational algebra MINUS/DIFFERENCE corresponds to EXCEPT in the SQL standard. But MySQL does not have it. You can do it using LEFT JOIN, NOT IN or NOT EXISTS instead.
I'm trying to select mltiple rows from tow table :
first table is donor
CREATE TABLE donor(
donor_number INT NOT NULL AUTO_INCREMENT,
d_name VARCHAR(30) NOT NULL,
mobile_number INT NOT NULL,
blood_group VARCHAR(20) NULL,
dob DATE NOT NULL,
gender ENUM('male','female') NOT NULL,
govid INT(10) NOT NULL,
PRIMARY KEY (donor_number )
);
second table is blood_donation
CREATE TABLE blood_donation(
donor_number INT NOT NULL,
date_of_donate DATE NOT NULL,
blood_group VARCHAR(20) NULL,
serial_number INT(10) NOT NULL,
blood_component ENUM('wb','prcb') NOT NULL,
PRIMARY KEY (donor_number , date_of_donate ),
FOREIGN KEY (donor_number) REFERENCES donor(donor_number)
);
with this select statement:
SELECT
serial_number,
blood_group
FROM blood_donation
WHERE date_of_donate = '2012-07-18'
UNION ALL
SELECT
blood_group
FROM donor
WHERE donor.donor_number=blood_donation.donor_number;
but, I get error
SQL state 42S22: Unknown column 'blood_donation.donor_number' in 'where clause'
any idea????
Actually you should not be using UNION but JOIN :)
you query will look like this
SELECT
blood_donation.serial_number,
donor.blood_group
FROM
blood_donation ,
donor
WHERE donor.donor_number = blood_donation.donor_number AND date_of_donate = '2012-07-18' ;
A UNION is used to combine more than one result set into a single result set - and each result set must have the same set of columns.
What you need is a JOIN, which is how you link multiple tables together on foreign keys etc and would be something like this:
SELECT
serial_number,
blood_group
FROM blood_donation
INNER JOIN donor ON donor.donor_number=blood_donation.donor_number
WHERE date_of_donate = '2012-07-18'
SELECT
dd.serial_number,
dd.blood_group
FROM blood_donation dd
inner join
donor d
on d.donor_number=dd.donor_number
WHERE dd.date_of_donate = '2012-07-18';
UNION is not what exactly you need, Read some more about JOINS. Also please change the selection alias of columns as per the need. And you can use Left Join instead of Inner Join if you don't want a mandatory join condition on tables.