1

グループごとの最大値を使用するクエリに本当に苦労しています。どんな助けでも大歓迎です。グループごとの最大値を使用してはならない場合は、遠慮なく指摘してください。

私は 2 つのテーブルapplicationとを持っていemailます。1 つのアプリケーションで多数の電子メールを扱うことができます。私がクエリでやろうとしているのは、アプリケーションからすべての詳細を取得し、電子メール テーブルに参加することです (実際には、電子メールが返信されたかどうかを示す別のテーブルの電子メールから外部キーを取得するだけです)。 max(timestamp) に基づいて送信された電子メール。これが、グループごとの最大値を使用しようとしている理由です。

私はこれを試しましたが、各行の複製を作成しているようです:

SELECT  `application` . * ,  `email1`.`student_email_id` AS  `email_student_email_id` 
FROM  `application` 
LEFT JOIN (
  SELECT MAX( tstamp ) AS tstamp, id, student_email_id, application_id
  FROM email
  GROUP BY id, student_email_id, application_id
) AS email1 ON  `email1`.`application_id` =  `application`.`id` 
WHERE  `application`.`status` =  'returned'

これは最初は機能しているように見えましたが、現在問題を引き起こしています。かなりずさんなコードだと確信しています。

select `application`.*, `email1`.`student_email_id` as `email_student_email_id`
from `application` 
left join (
  select student_email_id, max(tstamp) as tstamp, application_id
  from email 
  group by application_id, tstamp
  order by tstamp desc
  limit 1) as email1 on `email1`.`application_id` = `application`.`id` 
where `application`.`status` = 'returned'

さらに多くのコードが必要な場合は、お問い合わせください。ありがとう。

私のデータベースのセットアップに必要な場合と、何が起こっているのかをさらに明確にします(重要でない部分は省略しています):

Application Table
+----+----------+
| id |  status  |
+----+----------+
|  1 | returned |
+----+----------+

Email Table
+----+------------+----------------+------------------+
| id |   tstamp   | application_id | student_email_id |
+----+------------+----------------+------------------+
|  1 | 2014-12-26 |              1 | NULL             |
|  2 | 2014-12-27 |              1 | 3                |
+----+------------+----------------+------------------+

クエリは次のように表示されます。

+----+----------+------------------------+
| id |  status  | email_student_email_id |
+----+----------+------------------------+
|  1 | returned |                      3 |
+----+----------+------------------------+

上記の最初の解決策はすべての重複を示しており(おそらく私はほぼそこにいます)、2番目の解決策は結合されたテーブル列に対してnullを示していますが、少なくとも1つの段階または分離では機能したと確信しています!

4

1 に答える 1

4

Email個別の ごとに、テーブル内の最新の行を探していますapplication_id

それを取得するためのサブクエリは正しくありません。これを取得する方法は次のとおりです。

SELECT s.application_id, e.student_email_id
  FROM email e
  JOIN (
         SELECT MAX(tstamp) tstamp, application_id
           FROM email
          GROUP BY application_id
       ) s ON e.application_id = s.application_id AND e.tstamp = s.tstamp

これを行う別の方法があり、それはより効率的かもしれません。id列が自動インクリメント列である場合に機能します。

SELECT s.application_id, e.student_email_id
  FROM email e
  JOIN (
         SELECT MAX(id) id
           FROM email
          GROUP BY application_id
       ) s ON e.id = s.id

これらの前のサブクエリのいずれかが、各 application_id の最新の student_email_id を取得します。2 つ目は、JOIN を使用して各 application_id の最大 ID 番号のみを抽出し、その ID を使用して最新の student_email_id を見つけます。

あなたのサブクエリはこれでした。あなたが望んでいたものは得られません。

 SELECT MAX( tstamp ) AS tstamp, id, student_email_id, application_id /*wrong*/
   FROM email
  GROUP BY id, student_email_id, application_id 

これを ID でグループ化しました。つまり、すべての詳細行を取得することになります。それはあなたが望むものではありません。これでも

 SELECT MAX( tstamp ) AS tstamp, student_email_id, application_id  /*wrong*/
   FROM email
  GROUP BY student_email_id, application_id 

application_id 値ごとに複数のレコードが得られます。

したがって、必要なクエリは次のとおりです。

SELECT  application.* ,  email1.student_email_id AS  email_student_email_id 
  FROM  application 
  LEFT JOIN (
              SELECT s.application_id, e.student_email_id
                FROM email e  
                JOIN (
                       SELECT MAX(id) id
                         FROM email
                        GROUP BY application_id
                     ) s ON e.id = s.id
           ) AS email1 ON  email1.application_id =  application.id 
 WHERE application.status =  'returned'

このようなクエリを設計するときは、最も内側のサブクエリから始めて、内側から外側にテストするのが賢明です。

于 2014-12-26T23:32:23.440 に答える