5

テーブル内のすべてのDISTINCTユーザーについて、テーブル内の最初の最小値とそれが発生する日付を見つけようとしています。

これは、テーブルスキーマといくつかのサンプルデータです。

CREATE TABLE diet_watch (
  entry_date date NOT NULL,
  user_id    int default 1,
  weight     double precision NOT NULL
);

INSERT INTO diet_watch VALUES ('2001-01-01', 1, 128.2);
INSERT INTO diet_watch VALUES ('2001-01-02', 1, 121.0);
INSERT INTO diet_watch VALUES ('2001-01-03', 1, 122.3);
INSERT INTO diet_watch VALUES ('2001-01-04', 1, 303.7);
INSERT INTO diet_watch VALUES ('2001-01-05', 1, 121.0);
INSERT INTO diet_watch VALUES ('2001-01-01', 2, 121.0);
INSERT INTO diet_watch VALUES ('2001-01-06', 2, 128.0);

私が思いついたSQLはこのスニペットにあります

それ以来、それは正しくないという通知を受けました。おそらく誰かが私のSQLの問題を説明できるでしょうか。

注:可能であればANSI SQLを使用したいのですが、PostgreSQLを使用しているため、特定の種類のSQLを使用する必要がある場合は、PGで動作する必要があります。

4

3 に答える 3

6

注:ウィンドウ関数がANSISQLであるかどうかはわかりません

WINDOW関数はSQL:2003仕様の一部です:http: //en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function(Thx @a_horse_with_no_name)

これを試して:

http://sqlfiddle.com/#!1/7aa4e/22

SELECT *
  FROM 
    (
     SELECT a.*, 
            ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY weight) AS Position
       FROM diet_watch a

    ) a
    WHERE a.Position = 1 
于 2012-07-17T20:16:21.250 に答える
1

まず、クエリは不必要に複雑です。グループbyをサブクエリに入れて、外部クエリを削除するだけです。

@Chanduによって言及されたwindows関数は、非常に優れたソリューションです。これはANSISQLであり、postgresはそれをサポートしています。ただし、すべてのデータベースがそうであるわけではありません。別の方法は次のとおりです。

select dw.*
from diet_watch dw join
     (select user_id, min(entry_date) as mindate
      from diet_watch dw
      group by user_id
     ) dwmin
     on dw.user_id = dwmin.user_id and dw.entry_date = dwmin.mindate

元のクエリが機能しない理由は、最小のentry_dateに最小の重みがない可能性があるためです。クエリは、各フィールドの最小値を個別に取得します。このバージョンは最小の日付を見つけ、それを元のテーブルに結合して、その日の重み(およびその他の情報)を取得します。

于 2012-07-17T20:23:40.417 に答える
1

各ユーザーが最小体重を初めて達成した場合は、これでうまくいくと思います。テストデータを見ると、ユーザー1は最低121を2回達成していますが、最初のデートが必要ですか?私の知る限り、これはすべてのSQLエンジンで機能するはずです。

SELECT min(dw.entry_date), dw.user_id, dw.weight FROM diet_watch dw,
    (SELECT min(weight) AS "weight", user_id FROM diet_watch GROUP BY user_id) mins
WHERE dw.user_id = mins.user_id AND dw.weight = mins.weight
GROUP BY dw.user_id, dw.weight

内側の選択は、各ユーザーの最小体重を見つけます。その日にさらに1分が必要です。そうしないと、そのユーザーの最小体重が初めて達成された時間を具体的に選択できなくなるためです。

http://sqlfiddle.com/#!1/7aa4e/51/0

于 2012-07-17T20:34:45.677 に答える