I am stuck on a mySQL query that I just can't get my head around. I am currently writing a PHP program that will help with the issue of textbooks. I have a mySQL database with 2 tables.
Books table
PID ISBN BKNAME CID
Issued table
PID SNR ISBN CAMPUSNR DATE
The person issuing the books types in a student number and all the books that the student must receive for the course that he is enrolled in gets displayed. Like this:
$stmt = $db->prepare("SELECT isbn,bkname,cid FROM books WHERE (cid = :course)");
$stmt->bindValue(':course', $StudCourse, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
This gets displayed on screen with a checkbox after each book. The issuer then ticks the books that he is giving the student and then clicks on a issue button. This data is then inserted in the database, like this:
$stmt = $db->prepare("INSERT INTO issued(snr,isbn,campusnr,date) VALUES (:snr,:isbn,:campusnr,:date)");
$stmt->bindValue(':snr', $Studnr, PDO::PARAM_INT);
$stmt->bindValue(':isbn',$Ticked[$Num], PDO::PARAM_INT);
$stmt->bindValue(':campusnr', $Campus, PDO::PARAM_INT);
$stmt->bindValue(':date', $IssueDate, PDO::PARAM_STR);
The problem with this is that if more books are to be issued later to the student running the first statement, leads to an error where the same books may be issued again if the issuer ticks the wrong box after the books.
Is there a way to display in the first statement only the books still needed to be issued. I have tried the following mySQL statement:
SELECT *
FROM books
INNER JOIN issued ON books.isbn = issued.isbn
WHERE snr = '151107549'
AND NOT EXISTS (
SELECT isbn, bkname, cid
FROM books
WHERE cid = 'NC3OA'
)
But with this I get no results. Can a mySQL guru maybe give some help?
SELECT books.isbn,books.bkname,books.cid
FROM books
LEFT JOIN issued ON books.isbn = issued.isbn AND issued.snr = :snr
WHERE books.cid = :course AND issued.isbn IS NULL
ORDER BY books.isbn ASC
Take a look at this great figure explaining JOIN
s:
You want all rows from books
with a specific cid
. Now to remove the rows from issued
, you can do a LEFT JOIN
with a check if the key is NULL
:
SELECT books.isbn, books.bkname, books.cid FROM books
LEFT JOIN issued
ON books.isbn = issued.isbn
WHERE cid = :course
AND issued.isbn IS NULL
You are right to use NOT EXISTS here, for you are looking for those books where no issue entry exists yet. However, you are not using the EXISTS clause correctly. You are asking: Give me only results if there exist no books with cid NC3OA in the database, so you never get any record. (And somehow your statement looks quite confused; the inner join would give you the issued rather than the non-issued books.)
What I understand is: You want all books for a certain course except those that are already issued to the student. Here is the correct statement:
SELECT *
FROM books
WHERE cid = 'NC3OA'
AND NOT EXISTS
(
SELECT *
FROM issued
WHERE issued.isbn = books.isbn
AND snr = '151107549'
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.