如何以模块化方式构成Database.Esqueleto查询,以便在定义“基本”查询和相应的结果集之后,可以通过添加其他内部联接和where表达式来限制结果集。
另外,由于基本查询不是照此执行的,而是使用LIMIT和OFFSET的修改版本,因此如何将返回实体列表(或字段元组)的基本查询转换为对结果集进行计数的查询。
Yesod书中采用的以下不正确的Haskell代码段有望阐明我的目标。
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts #-}
import qualified Database.Persist as P
import qualified Database.Persist.Sqlite as PS
import Database.Persist.TH
import Control.Monad.IO.Class (liftIO)
import Data.Conduit
import Control.Monad.Logger
import Database.Esqueleto
import Control.Applicative
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Person
name String
age Int Maybe
deriving Show
BlogPost
title String
authorId PersonId
deriving Show
Comment
comment String
blogPostId BlogPostId
|]
main :: IO ()
main = runStdoutLoggingT $ runResourceT $ PS.withSqliteConn ":memory:" $ PS.runSqlConn $ do
runMigration migrateAll
johnId <- P.insert $ Person "John Doe" $ Just 35
janeId <- P.insert $ Person "Jane Doe" Nothing
jackId <- P.insert $ Person "Jack Black" $ Just 45
jillId <- P.insert $ Person "Jill Black" Nothing
blogPostId <- P.insert $ BlogPost "My fr1st p0st" johnId
P.insert $ BlogPost "One more for good measure" johnId
P.insert $ BlogPost "Jane's" janeId
P.insert $聽Comment "great!" blogPostId
let baseQuery = select $ from $ \(p `InnerJoin` b) -> do聽
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` (val "J%"))
return (p,b)
-- Does not compile
let baseQueryLimited = (,) <$> baseQuery <*> (limit 2)
-- Does not compile
let countingQuery = (,) <$> baseQuery <*> (return countRows)
-- Results in invalid SQL
let commentsQuery = (,) <$> baseQuery
<*> (select $聽from $ \(b `InnerJoin` c) -> do
on (b ^. BlogPostId ==. c ^. CommentBlogPostId)
return ())
somePosts <- baseQueryLimited
count <- countingQuery
withComments <- commentsQuery
liftIO $ print somePosts
liftIO $ print ((head count) :: Value Int)
liftIO $ print withComments
return ()
对于LIMIT
和COUNT
,hammar的答案是完全正确的,因此我不会深入研究它们。我只是重申一下,一旦使用,select
您将无法再次以任何方式更改查询。
对于JOIN
s,当前您无法INNER JOIN
使用在其他from
(nor (FULL|LEFT|RIGHT) OUTER JOIN
)中定义的查询执行。但是,您 可以 执行隐式联接。例如,如果您已定义:
baseQuery =
from $ \(p `InnerJoin` b) -> do
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` val "J%")
return (p, b)
然后您可能会说:
commentsQuery =
from $ \c -> do
(p, b) <- baseQuery
where_ (b ^. BlogPostId ==. c ^. CommentBlogPostId)
return (p, b, c)
然后,Esqueleto会生成以下内容:
SELECT ...
FROM Comment, Person INNER JOIN BlogPost
ON Person.id = BlogPost.authorId
WHERE Person.name LIKE "J%"
AND BlogPost.id = Comment.blogPostId
不漂亮,但可以完成INNER JOIN
s的工作。如果需要执行a,OUTER JOIN
则必须重构代码,以使所有OUTERJOIN
s都相同from
(请注意,您可以在OUTER JOIN
s之间进行隐式联接就可以了)。
subcompany.hbm.xml 子单位表 branch.java 指定表 我需要帮助编写条件查询使用提供的SQL。
问题内容: 在带有mysql的Rails 3中,假设我有两个模型,Customers和Purchases,显然是purchase_to customer。我想找到2个或更多订单的所有客户。我可以简单地说: 有效地,上面的行查询Customer.all和Purchase.all的大小,然后在ruby中进行“选择”类型的处理。在大型数据库中,我更希望避免在ruby中进行所有这种“选择”计算,而让mys
问题内容: 我绝对是SQL的新手,我一直在努力用Postgresql中的以下表结构编写一个复杂的查询: 查询的目的是获取每个用户的报告类型数量,并将其显示在一列中。有三种不同类型的报告。 使用group-by的简单查询将解决问题,但将其显示在不同的行中: 问题答案:
我想知道是否可以将一个实体配置为自动从另一个实体加载数据。前任。 和 当findby、findbyone等访问accountsUsers时,是否可以设置accountsUsers以自动加载所有帐户数据。关系为accountsUsers.userid=accounts.id。 如果没有,我将如何在使用原则的连接中做到这一点。我知道如何使用纯原始sql。 选择*从帐户a左加入帐户用户ba.id=b.u
如何使用Laravel的查询构建器构建相同的查询(如果可能的话)是使用Eloquent更好,还是应该使用DB::Select?
有没有办法在没有显式连接的实体上编写条件查询?通过显式连接,我的意思是数据库中的两个表没有外键关系,但一些列需要从两个表中提取,因此在查询中需要连接。我知道具有join的查询可以用‘In’子句编写,而条件查询可以用‘In’条件编写。我已经写了这种情况下的HQL,但请告诉我如何编写这种情况下的标准查询。 先谢谢了