こんな構成のデータベースにある3テーブルの各レコードをusr_member_idでjoinしてとるSQLを書いてみた
でコード、yesodのHandlerモナドの中から呼んでいるのでHandler Appになっているのは許してもらうとしてこんな感じ
getUsers :: Param -> HandlerFor App ([(E.Entity UsrMember, E.Value Text, E.Value Int)], Int)
getUsers p = runDB $ do
let pagePerLine = fromIntegral $ unPagePerLine p
page = fromIntegral $ unPageNum p
reqId = fromIntegral $ unReqId p
typeIds = [1, 2]
(ageFrom, ageTo) = (unAgeFrom p, unAgeTo p)
baseQuery = E.from $ \(usrMember `E.InnerJoin` usrImage `E.InnerJoin` usrAgeView) -> do
E.on $ usrMember E.^. UsrMemberUsrMemberId E.==. usrAgeView E.^. UsrAgeViewUid
E.on $ usrMember E.^. UsrMemberUsrMemberId E.==. usrImage E.^. UsrImageUsrId
E.where_ $ do
let reqQuery = usrMember E.^. UsrMemberReqId E.==. E.val reqId
ageQuery = usrAgeView E.^. UsrAgeViewAge E.>=. E.val ageFrom
E.&&. usrAgeView E.^. UsrAgeViewAge E.<=. E.val ageTo
usrMember E.^. UsrMemberTypeId `E.in_` E.valList typeIds
E.&&. (if reqId > 0 then reqQuery else E.val True)
E.&&. (if ageFrom > 0 && ageTo > 0 then ageQuery else E.val True)
E.&&. usrImage E.^. UsrImageImageDiv E.==. E.val 2
return (usrMember, usrImage E.^. UsrImageFileName, usrAgeView E.^. UsrAgeViewAge)
baseQueryPage = do r <- baseQuery; E.offset (pagePerLine * page); E.limit pagePerLine; return r
cnt <- Import.length <$> E.select baseQuery
s <- E.select baseQueryPage
return (s, cnt)
where句に条件で追加する方法、haskellのifは型を合わせる必要があるので、then、elseの
ところをexpr(Value a)にする必要があって、「E.val True」にするのは気がつかなかった、あとはoffsetだのlimitだのを後で追加する方法とかも参考になった。
ただ、カウントの取得方法がわからず、上のコードだと無駄なとり方になっているのはごめんなさい、どうしてもjoinした場合のcountRowsやその他の集計関数がうまく組み込めなかった。
どなたか教えては頂けないでしょうか?...
コードはこちらに置いておきます、「えすきゅーぅうれっちゅ」ネタでした。

0 件のコメント:
コメントを投稿