如何在不使用 UNION 的情况下在相关表之间执行此查询?
假设我有两个单独的表,我要观察它们来查询。这两个表都与第三个表有关系。如何使用单个非基于 UNION 的查询来查询两个表?
这是一个理论上的例子。我有一个用户表。该用户可以同时拥有 CD 和书籍。我想通过与字符串匹配的单个查询来查找该用户的所有书籍和 CD(在本例中为“awesome”)。
基于 UNION 的查询可能如下所示:
SELECT "book" AS model, name, ranking
FROM book
WHERE name LIKE 'Awesome%'
UNION
SELECT "cd" AS model, name, ranking
FROM cd
WHERE name LIKE 'Awesome%'
ORDER BY ranking DESC
如何在没有 UNION 的情况下执行这样的查询?如果我从用户到书籍和 CD 进行简单的左连接,我们最终得到的结果总数等于匹配 CD 的数量乘以匹配书籍的数量。是否有 GROUP BY 或其他编写查询的方式来解决此问题?
(编辑:我想避免使用 Union 方法的原因是因为这实际上是一个 DQL 查询,而 Doctrine 不支持 UNION。如果没有 UNION 就无法做到这一点,我将采用本机 SQL 路线。此外,真正的查询包含一堆附加列,这些列在上面的示例中不能很好地相互映射。)
Suppose I have two separate tables that I watch to query. Both of these tables has a relation with a third table. How can I query both tables with a single, non UNION based query?
Here's a theoretical example. I have a User table. That User can have both CDs and books. I want to find all of that user's books and CDs with a single query matching a string ("awesome" in this example).
A UNION based query might look like this:
SELECT "book" AS model, name, ranking
FROM book
WHERE name LIKE 'Awesome%'
UNION
SELECT "cd" AS model, name, ranking
FROM cd
WHERE name LIKE 'Awesome%'
ORDER BY ranking DESC
How can I perform a query like this without the UNION? If I do a simple left join from User to Books and CDs, we end up with a total number of results equal to the number of matching cds timse the number of matching books. Is there a GROUP BY or some other way of writing the query to fix this?
(EDIT: The reason I would like to avoid the Union approach is because this is actually a DQL query and Doctrine does not support UNION. If there's no way to do this without UNION, I'll go the native SQL route. In addition, the real query contains a bunch of additional columns that do not map as nicely against one another in the above example.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
想想如何在面向对象的应用程序中对此进行建模。您将创建一个针对书籍和 CD 进行扩展的超类,然后您的用户将拥有一组
收藏品
。该集合中的任何给定对象要么是一本书,要么是一张 CD(或其他类型的收藏品),但它恰好具有这些子类型之一。您可以使用 SQL 执行类似的操作,通过创建与超类型相对应的表:
然后每个子类型都包含一个引用以使其可收集:
现在您可以执行查询并确保您不会得到笛卡尔积:
Think of how you'd model this in an OO app. You'd create a superclass that you extend for books and CD's, and your user would then own a set of
Collectibles
. Any given object in that set is either a book or a CD (or other type of collectible) but it has exactly one of these subtypes.You can do something similar with SQL, by creating a table corresponding to the supertype:
Then each subtype contains a reference to make it collectible:
Now you can do your query and be assured you won't get a Cartesian product:
如果您试图避免联合,一种方法是创建视图。
编辑:要 创建视图,您有两个
选项如果您的查询仅用于选择记录,那么应该没有问题
如果您需要可以更新的视图,那么如果您重构,它可能会飞起来:
EDIT2:我忘记评论 UNION ALL 是必须结束的事实UNION 除非您希望 MySQL 在每次运行视图/查询时开始在磁盘上构建索引(感谢 HLGEM)。
If you are trying to avoid union one way is to create view.
EDIT: To create view you have two options
In case your query is only for selecting records there should be no problem with
If you need view that can be updated then it might fly if you refactor:
EDIT2: I forgot to comment on the fact that UNION ALL is a must over UNION unless you want MySQL to start building index on the disk every time you run the view/query (thanks HLGEM).
除非有令人信服的理由不使用 UNION,否则就使用 UNION。
Unless there is a compelling reason to not use a UNION, then just use the UNION.
也许你可以尝试这样的事情......该示例假设第三个表称为 User:
Maybe you could try something like this... the example assumes the third table is called User: