こんな構成のデータベースにある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 件のコメント:
コメントを投稿