很抱歉我把这个问题表述得这么糟糕——我是编程新手。

我正在做的是,我在一个小型库管理器应用程序中使用 Java @NamedQuery。我有实体类 Book ,其属性为 bookid、标题、作者等。Booktaken 具有属性 id、clientid、bookid、datetaken。因此 Bookstaken.bookid 是引用 Book.bookid 的外键。Booktaken 包含所有已取走的书籍,Book 包含图书馆拥有的所有书籍(但目前不一定有)。

我已经取回了所有的书 采取 使用这个命名查询:

@NamedQuery(name = "Taken", query = "SELECT b FROM Book b, Bookstaken t WHERE b = t.bookid")

但现在我想创建一个名为“Not take”的命名查询,它将检索所有具有...的书籍你知道,没有被带走。因此本质上是查询“Taken”的互补组。

我已经尝试过这个:

@NamedQuery(name = "Not taken", query = "SELECT b FROM Book b, Bookstaken t WHERE b <> t.bookid")

(我尝试用 != 替换 <>)

但该声明给出了整组书籍,其中的每一本,并多次给出了该组书籍。为什么会发生这种情况?我在 SQL 方面从来没有天赋...我该如何解决它?

谢谢

有帮助吗?

解决方案

首先,你必须意识到你在这里没有SQL,而是JPQL。这些是两种不同的语言。

第二,您的查询显示您有误解。书籍实体不应该有一个简要的字段。它应该有一个与书籍的一个要关联,因此是书籍的领域。

最后,您所拥有的查询是不正确的。您想要的是所有书籍都没有引用本书的任何书籍实体:

select b from Book b where not exists (
    select bt.id from BookTaken bt where bt.bookid = b.id)
.

其他提示

首先,您应该确定您正在比较的内容。在:

@NamedQuery(... "SELECT b FROM Book b, Bookstaken t WHERE b <> t.bookid")

您正在比较一个 Book 带有一个 id (Bookstaken.bookid)。后者可能是一个 Integer, ,因此总是不同于 Book.

根据这个理由,您应该使用: "SELECT b FROM Book b, Bookstaken t WHERE b.bookid != t.bookid", , 作为 b != t.bookid 会回来 true 对于所有元素。


但这可能不只是您想要的。正如评论中正确指出的那样,上述结果将产生笛卡尔积。你想要的是更符合 SQL 的风格 JOIN, , A LEFT OUTER JOIN, , 更具体。

正如在 JPQL 中一样, LEFT JOIN 实际上具有 SQL 的语义 LEFT OUTER JOIN, ,你可以使用,然后:

@NamedQuery(name = "Not taken", query = 
"SELECT b FROM Book b LEFT JOIN Bookstaken t ON b.bookid = t.bookid "+
"WHERE t.bookid IS NULL")

You're approaching the query the wrong way. You're telling the database that you want all pairs of rows from Book and Bookstaken where the Bookstaken doesn't match the Book. As you can imagine, there are lots of pairs of rows that don't match, so you're getting lots of rows, which is not what you want.

What you really want is to select all rows in Book that don't have a corresponding rown in Bookstaken. You can do this with SELECT b from Book WHERE NOT EXISTS( SELECT * from Bookstaken t WHERE t.bookid = b.bookid ).

Or you can use a LEFT OUTER JOIN to join Books to their matching Bookstakens but leave in the result set any Books that don't have a corresponding Bookstaken, and then use WHERE t.bookid = NULL to get only the ones without a corresponding Bookstaken.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top