1

これはよくある質問です。以前に質問したことがあり、さらにいくつか調べたことがありますが、それでも、これに基づいてクエリを実行しても、機能させることができません。参照: max(timestamp)に基づくMysql結合と右テーブルの最大値のmysqlLEFT結合

基本的に、私はさまざまなアイテム('chairs'、'tables')のテーブルを持っており、各タイプには、特定の椅子またはテーブルの独自のIDを持つレコードがあります。次に、現在の場所を含め、これまでに行ったすべての場所を保持する場所テーブルがあります。現在の場所は、MAXタイムスタンプで示されます。

私のクエリは、すべてのアイテムを取得し、現在の場所に参加することを目的としています。私は他の人が言ったことをフォローしましたが、それは私にとってはうまくいきません。どんな助けでも大歓迎です。

編集:どのように失敗するかは言いませんでした:レコードを取得して結合し、最大タイムスタンプを返しますが、MAX(タイムスタンプ)レコードに対応するレコード情報は返しません。したがって、正しいタイムスタンプが得られますが、フロアなどはMAXタイムスタンプのレコードからのものではありません。

ありがとう!

クエリ:

$q = "SELECT
        'chairs' AS work_type,
        chairs.id AS work_id,
        chairs.title,
        chairs.dimensions,
        CurrentLocations.floor,
        CurrentLocations.bin,
        CurrentLocations.bay,
        CurrentLocations.other
       FROM chairs
             LEFT JOIN ( 
                        SELECT 
                              locations.id AS loc_id,
                              locations.work_type AS clwt,
                              locations.work_id AS clwi,
                              locations.floor,
                              locations.bin,
                              locations.bay,
                              locations.other,
                              MAX(locations.timestamp) AS latestLocation
                            FROM
                               locations
                            GROUP BY
                               locations.work_type, locations.work_id
                            ) CurrentLocations
                ON CurrentLocations.clwi = chairs.id AND CurrentLocations.clwt = 'chairs'
        WHERE cur_loc LIKE '%19th Street%'
        ORDER BY 
            FIELD(floor, 'Basement', '3rd Floor', '4th Floor', '5th Floor'), 
            bin, 
            bay,
            other";
4

1 に答える 1

8

これを試して:

    SELECT
        'chairs' AS work_type,        -- do you really need this in the result?
        c.id AS work_id,
        c.title,
        c.dimensions,
        l.floor,
        l.bin,
        l.bay,
        l.other
    FROM 
        chairs AS c
      LEFT JOIN
        ( SELECT work_id,
                 MAX(timestamp) AS latestLocation
          FROM   locations
          WHERE  work_type = 'chairs'
          GROUP BY work_id
        ) AS cl                                  -- CurrentLocations
          ON  cl.work_id = c.id
      LEFT JOIN
        locations AS l 
          ON  l.work_type = 'chairs'
          AND l.work_id = cl.work_id
          AND l.timestamp = cl.latestLocation 
    WHERE 
        c.cur_loc LIKE '%19th Street%'
    ORDER BY 
        FIELD(l.floor, 'Basement', '3rd Floor', '4th Floor', '5th Floor'), 
        l.bin, 
        l.bay,
        l.other ;

説明:

あなたがしたい:

基本的に、さまざまなアイテム ( chairstables) のテーブルがあり、各タイプには特定の椅子またはテーブルの独自の ID を持つレコードがあります。次にlocations、現在の場所を含め、これまでに行ったすべての場所を保持するテーブルがあります。現在の場所は、最大で示されますtimestamp

私のクエリは、すべてのアイテム (椅子) を取得し、現在の場所に参加するためのものです。

したがって、すべてのアイテム (つまり) については、最新のchairのみが必要です。テーブル内のすべてについて、 が必要です。すでにわかっているように、これは で簡単に見つけることができます。 locationwork_idlocationMAX(timestamp)GROUP BY

        ( SELECT work_id,
                 MAX(timestamp) AS latestLocation
          FROM   locations
          GROUP BY work_type
                 , work_id
        ) AS cl

ただし、そのテーブルの他の列も使用する必要があり、それらを単に選択リストに追加すると、間違った結果が表示されます。(ほとんどの DBMS では、リストにない列を使用するには、GROUP BYに適用したように、集計関数を適用する必要がMAX()あることに注意してくださいtimestamp。MySQL ではこの動作が許可されており、適切に使用すると、いくつかの利点があります。しかし、 Postgres は 100% フェイルプルーフを実装していないため、このような場合に適用すると間違った結果が得られる可能性があります. Postgres はこの機能をはるかに優れた方法で実装しており、誤った結果を許容しません.)

したがって、上記のGROUP BYクエリを派生テーブルとして使用し (任意の名前を付けclます)、リストのすべての列と集計された列 ( )を使用してテーブルにCurrentLocation結合します。locationsGROUP BYtimestamp

      JOIN
        locations AS l 
          ON  l.work_type = cl.work_type
          AND l.work_id = cl.work_id
          AND l.timestamp = cl.latestLocation 

その後、chairs通常どおりテーブルに参加できます。元のクエリにa があったので、chairs LEFT JOIN locationsこれらも回答に残しました。

もう 1 つのマイナーな変更は、 を持っていたので、テーブルCurrentLocations.work_id = 'chairs'からそれらの行だけが必要だったことです。locationsしたがって、最初にグループ化を行ってから、その条件に一致しないすべての行を拒否するのはかなり冗長です。最初に条件を適用してからグループ化する方がおそらく効率的です。それに応じて、最終的なグループ化クエリと結合条件が変更されます。

(work_type, work_id, timestamp)また、インデックスをオンにするとクエリの効率が向上することにも注意してください(clサブクエリはそのインデックスのみを使用して処理されJOIN locations、 もインデックスを使用して、場所テーブルから必要な行を見つけます)。

于 2013-01-16T23:13:20.730 に答える