2

すべてStatusUpdateの とそれぞれUserの を選択する Esqueleto クエリがあります。StatusUpdateごとに1 つだけに制限したいと思います。当日からは sUserのみです。StatusUpdate

有効な SQL クエリがありますが、それを有効な Esqueleto に変換するのに苦労しています。

SELECT "email", "subject"
FROM "status_update"
LEFT JOIN "user"
ON ("status_update"."user" = "user"."id")
WHERE "status_update"."id"
IN (SELECT MAX("status_update"."id") FROM "status_update" GROUP BY "status_update"."user")

私がこれまでに持っているもの:

  statusUpdates <- runDB
    $ E.select
    $ E.from $ \(status_update `E.LeftOuterJoin` user) -> do

      E.on (status_update ^. StatusUpdateUser E.==. user ^. UserId)

      E.where_ ((status_update ^. StatusUpdateId) `E.in_`
        (E.subList_select $ E.from $ \(status_update) -> do
          E.groupBy (status_update ^. StatusUpdateUser)
          return (status_update ^. StatusUpdateId)))

      return
        ( status_update ^. StatusUpdateId
        , status_update ^. StatusUpdateSubject
        , status_update ^. StatusUpdateMessage
        , user ^. UserEmail
        )

…次の出力が生成されます。

SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "status_update"
LEFT OUTER JOIN "user"
ON "status_update"."user" = "user"."id"
WHERE "status_update"."id"
IN (SELECT "status_update2"."id" FROM "status_update" AS "status_update2" GROUP BY "status_update2"."user"); []

欠けているのはMAX、2番目の選択の機能だけです。クエリのさまざまな部分に絞り込もうとしていE.max_ますが、何も機能していないようです。

ヘルプ?

4

1 に答える 1

3

subList_selectを使用して呼び出そうとする代わりに、サブクエリをmax_使用して、日付と制限 1 で並べ替えることができます。sub_select

これは私が見つけた解決策であり、トリックを行うようです:

    result <- select $ from $ \(user, status_update) -> do
        let subquery = from $ \status_update2 -> do
            where_ (status_update2 ^. StatusUpdateUser ==. user ^. UserId)
            where_ (date (status_update2 ^. StatusUpdatePosted) ==. date now)
            orderBy [desc (status_update2 ^. StatusUpdatePosted)]
            limit 1
            return (status_update2 ^. StatusUpdateId)

        where_ (status_update ^. StatusUpdateId ==. sub_select subquery)
        where_ (user ^. UserId ==. status_update ^. StatusUpdateUser)
        return
            ( status_update ^. StatusUpdateId
            , status_update ^. StatusUpdateSubject
            , status_update ^. StatusUpdateMessage
            , user ^. UserEmail
            )

結果の SQL は次のとおりです。

SELECT "status_update"."id", "status_update"."subject", "status_update"."message", "user"."email"
FROM "user", "status_update"
WHERE ("status_update"."id" = (SELECT "status_update2"."id"
    FROM "status_update" AS "status_update2"
    WHERE ("status_update2"."user" = "user"."id")
    AND (date("status_update2"."posted") = date(date(?)))
    ORDER BY "status_update2"."posted" DESC
    LIMIT 1))
AND ("user"."id" = "status_update"."user")

StatusUpdates私が定義dateした「今日からのみ」の条件を満たし、nowインポートすることにより、次のようにDatabase.Esqueleto.Internal.Sqlなります。

date :: SqlExpr (Value UTCTime) -> SqlExpr (Value Int)
date d = unsafeSqlFunction "date" d

now :: SqlExpr (Value UTCTime)
now = unsafeSqlFunction "date" (val "now" :: SqlExpr (Value String))

ただし、「当日から」が正確に何を意味するかは、別のものである可能性があります (過去 24 時間、特定のタイムゾーンなど)。

于 2015-12-07T20:27:41.863 に答える