简体   繁体   中英

mySQL Query NOT EXISTS

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM