2012-07-17 5 views
5

テーブル内の最初の最小値とその発生日をテーブル内のすべてのDISTINCTユーザーに対して検索しようとしています。FIRSTテーブルの最低値と、それが発生した日付を別個のユーザーごとに返します。

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

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はthis snippet

にここにある、私は以来、それが間違っていることを知らされている、おそらく誰かが何かを説明することができます私のSQLの問題は?

注:可能であればANSI SQLが好きですが、私はPostgreSQLを使用していますので、SQLの特定のフレーバーを使用する必要がある場合は、PGで動作する必要があります。

+0

私は現在SQL FIddleにアクセスできません。あなたはあなたの質問を投稿できますか? – RedFilter

+0

@RedFilter - SQL Fiddleはあなたのために働いていませんか?どうしたの? –

+0

@JakeFeaselそれは今良いことだ - 私はサーバーがちょうど打撃を受けていたと思う、ページはレンダリングするのに数分かかった。しかしその後はOKだった。 – RedFilter

答えて

6

注:2003仕様:: http://en.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function(Thxを @a_horse_with_no_name)

はこれを試してみてください:

ウィンドウ関数は、ANSI SQL

ウィンドウ関数は、SQLの一部であるかどうかわかりません

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 
+0

はい、ウィンドウ関数**は** ANSI SQL(2003年以降)です。 –

+0

@a_horse_with_no_nameここに投稿するオンラインリファレンスを取得しようとしていました。あなたは1つの便利な場合は、plsそれを投稿できますか? – Chandu

+0

http://ja.wikipedia.org/wiki/Window_function_%28SQL%29#Window_function –

1

まず、クエリが不必要に複雑になります。サブクエリにグループを置くだけで、外側のクエリを削除することができます。

@Chanduに言及されているwindows関数は非常に良い解決策です。これはANSI SQLであり、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に最小の重みがない可能性があるからです。クエリは、各フィールドの最小値を個別に取得します。このバージョンでは最小の日付が検索され、元のテーブルに戻ってその日の重み(およびその他の情報)が取得されます。

+0

ほとんどすべてのDBMSは、ウィンドウ機能をサポートしています。非常に少数しかありません(特にMySQLとSQLite) –

+0

+1、主にOPのクエリが失敗する理由について – dbenham

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 

インナーセレクトは、各ユーザーの最小ウェイトを検出します。他の分は日付に必要です。そうしないと、そのユーザーの最小体重が達成された最初の時間を特に選択しないためです。

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

関連する問題