2009-05-03 10 views
0

開発中のアプリケーションでSQLiteを使用しています。
かなり複雑なクエリ(私のために複雑!)を実行しようとしていて、私が必要とする基本的な結果を得ましたが、最後のハードルを乗り越えることに悩まされています。Min()SQLで複数のテーブルを使用する

私は現在、私はそれが何をする必要があるかないこのクエリを持っている...

SELECT SUM(activity) 
FROM activities 
WHERE activity_id IN(SELECT name_id FROM foods GROUP BY name_id HAVING SUM(points) > 20); 

私はこのクエリに別の部品を追加する必要がありますが、それは私のために少し複雑得ている場所です。 3つのテーブルがあります....日付、食品、活動と私は特定のステートメントが真である限り、2つの異なるテーブルからの2つの値の間の最小数を含む結果セットの合計を見つける必要があります。基本的には

..

SELECT SUM(total) FROM (SELECT MIN(value from table1 which is determined by a value in table2, value from table3) AS total 
FROM table3 
WHERE value from table3 is contained in a result set from table1); 

以下のクエリは、私は構文が全くなかった場合に働くことを思いついた何か(笑!)です。これは機能しませんが、私は何をしようとしているのかをよりよく理解するためにそれを表示したかっただけです。

SELECT SUM(activity_amount) FROM (SELECT min((SELECT SUM(points) - 20 FROM foods WHERE name_id IN(SELECT pk FROM dates WHERE weekly=1) GROUP BY name_id), activity) AS activity_amount 
FROM activities 
WHERE activity_id IN(SELECT name_id FROM foods GROUP BY name_id HAVING SUM(points) > 20)); 

問題がMIN()の最初の値である....

SELECT SUM(points) - 20 FROM food WHERE name_id IN(SELECT pk FROM dates WHERE weekly=1) GROUP BY name_id 

その文は複数の値を生成するが、私はMIN()で他人と比較するために、これらの値が必要なのかにもかかわらず、私はそれらを一度に1つだけ必要とします...全体のセットとしてではありません。

上記のようなクエリを作成するにはどうすればよいですか?

EDIT ...より効果的に役立ついくつかのサンプルテーブル。おかげで私のオリジナルのポスト(動作しないもの)から、この元とクエリでjellomonkeyとhainstech

Table#1(dates) 

CREATE TABLE dates (pk INTEGER PRIMARY KEY, date INTEGER, weekly INTEGER) 
pk date  weekly 
1 05062009 1 
2 05072009 1 
3 05082009 2 

Table #2(foods) 

CREATE TABLE foods (pk INTEGER PRIMARY KEY, food VARCHAR(64), points DOUBLE, name_id INTEGER) 
pk food points name_id 
1 food1 12.0  1 
2 food2 9.0  1 
3 food3 5.0  1 
4 food4 15.0  2 
5 food5 14.0  2 
6 food6 12.0  3 

Table#3(activities) 

CREATE TABLE activities (pk INTEGER PRIMARY KEY, activity DOUBLE, activity_id INTEGER) 
pk activity activity_id 
1  5.0   1 
2  4.0   1 
3  2.0   2 
4  4.0   3 

は、私は1つvalue..8.0

MINを含む結果セットを探していることになる(26.0 -20、9.0)= 6.0
MIN(29.0から20、2.0)= 2.0
6.0 + 2.0 = 8.0

私はこのことができます願っています!

+0

あなたはアップタ​​イプでした!少しテーブルの例(可能な限り単純)と少し望ましい結果セット? – jellomonkey

+0

私は例を含めるために自分の投稿を編集しました。ありがとう!! – freddyD

答えて

2

あたり上記のクエリにHAVING、私はあなたが欲しいものを疑う占いを追加:

SELECT SUM(MIN(fp-20, ap)) FROM 
    (SELECT dates.pk AS fd, SUM(points) AS fp 
    FROM dates 
    JOIN foods ON name_id = fd 
    GROUP BY fd 
    HAVING fp >= 20) 
    JOIN 
    (SELECT dates.pk AS ad, SUM(activity) AS ap 
    FROM dates 
    JOIN activities ON activity_id = ad 
    GROUP BY ad) 
    ON fd = ad 

列名は、ちょっと、少なくともこれは8.0を与えず、副問い合わせは、あなたが言及他の番号を与え、その意味にゼロの接続を持っているように見えますが、 - )

+0

アレックス、ありがとう!これはすごくうまくいった。私があなたに尋ねる唯一のもう一つの事は、このクエリが日付からすべてのpkを考慮に入れていることです。 "weekly = 1"の場合、pkの日付のみを取得するにはどうすればよいですか?私はあなたが "... FROM date from name_id ...."という名前の料理を作ることができると思っています。私はそれを "毎週どこからでも行うことができます= 1 JOIN foods on name_id ...."それは働くだろうか? – freddyD

+0

アレックス、もう少し考えていますが、私が提案したことがうまくいくとは思いませんか? JOINでエラーが発生すると思いますか? – freddyD

+0

構文上、 'WHERE dates.weekly = 1'はJOINになり、両方の内部SELECTに必要です。 –

1

jellomonkeyと同意する - 詳細を表示しない限り、あなたが望むものを正確に理解することはできません。単純なテーブル定義、サンプルデータのいくつかの行、および期待される出力が役立ちます。ここ

は、その境界の二つの他のテーブルで定義されている範囲に基づいてテーブルから最小値を取得するための簡単な例である:

create table t1(t1id int primary key, value int) 
create table t2(t1id int, t2id int primary key, value int) 
create table t3(t2id int, t3id int primary key, value int) 

select 
    MIN(t1.value) 
from table1 as t1 
    join table2 as t2 on t2.t1id = t1.t1id 
    join table3 as t3 on t3.t2id = t2.t2id 
where t1.value between t2.value and t3.value 

これはの境界としてt2.valueとt3.valueを使用しますMIN()を見つける範囲。

EDIT - トンを助けるサンプルテーブルを投稿してくれてありがとう。いくつかの複雑なCASE文を使用して2つの値を比較することもできますが、それらを1つの行セットに持ち込み、通常のMIN集計を行うことになります。これは読みやすくなり、必要に応じてMIN入力に追加する情報を簡単に追加できるようになります。だからここに私はどうなるのかを簡単に強打です:

select 
    SUM(activity) 
from (
    select 
     min(activity) as activity 
     ,activity_id 
    from (
     select 
      SUM(activity) as activity, activity_id 
     from activities 
     group by activity_id 
     union all 
     select 
      SUM(points)-20 
      ,name_id 
     from foods 
     group by name_id 
     having SUM(points) > 20 
    ) as activitySum 
    where activity_id in (select pk from dates where weekly=1) 
    group by activity_id 
) as activityLesserOf 

編集#2 - であるかもしれないくらい頭スクラッチ後ニーズの明確化

+0

ちょっとありがたいです...あなたの投稿を見たときにサンプルテーブルを追加すると、私はすでに中間にいたので、とにかく終了しました。あなたの提案を試して実行します。 とにかく、OPを編集して – freddyD

+0

という例を追加しましたが、これはクエリが設計されていて実際には少し違ったものが必要でした。私がこれを実装しようとしている私のアプリケーションでは、ポイントが20より大きいname_idだけが気になります。合計(ポイント)を取って20を引いた値は、ポイントが20より大きい場合にのみ行われます。素晴らしいと私は十分なsqlでこれが起こるように部品を追加する場所を知っていたといいね...任意の考えですか? – freddyD

+0

@freddyD - 私が正しく理解していれば、SUM()が20未満の食物表からすべての集計を除外したいと思いますか? HAVINGを使用して集計後の値にフィルタを適用します。基本的にWHEREと同じですが、集計の前にWHEREが適用され、後にHAVINGが適用されます。上記のクエリに追加しましたが、これがあなたが探しているものかどうか私たちにお知らせください。 – ahains

関連する問題