2012-04-02 6 views
0

私は次の操作を実行したときに、私はエラーを取得:エラー相関フィールド

SELECT * 
from cGift c1 left join 
    (select c2.gidnumb, "t" new from cGift c2 where c2.gidnumb = 
     (select c3.gidnumb from cgift c3 where c3.id = c2.id and c3.date = 
      (select min(c4.date) from cgift c4 where c2.id == c4.id))) tNew 
    on tNew.gidnumb = c1.gidnumb 

基本的に私はそれに寄付金のリストとテーブルcgiftを持っています。私は、 "t"またはnullのいずれかを含む余分な列でcgiftを返すクエリが必要です。各寄付者(cgift.id)の最初の寄付(cgift.date)は「t」、残りはヌルです。

例:

gidnumb..id....date......new 
10.......1.....2/1/2010..null 
11.......2.....1/1/2010..t 
12.......3.....1/1/2010..t 
13.......1.....3/1/2010..null 
14.......2.....2/1/2010..null 
15.......4.....1/1/2010..t 
16.......1.....1/1/2010..t 

ヌルがブランまたはFまたはwtvrとすることができます。

誰かが私の質問に間違っていると教えてくれるのですか?

答えて

2

SELECT 
    cGift.gidnumb, 
    cGift.id, 
    cGift.date, 
    first.isfirst 
FROM cGift 
LEFT JOIN (
    SELECT id, MIN(date) AS date, 't' AS isfirst 
    FROM cGift 
    GROUP BY id 
) first ON cGift.id = first.id AND cGift.date = first.date 

UPDATE(アドレス指定の基準を追加):

人がで複数回寄付する場合その後、

ある
SELECT 
    cGift.gidnumb, 
    cGift.id, 
    cGift.date, 
    first.isfirst 
FROM cGift 
LEFT JOIN (
    SELECT 
     MIN(g.gidnumb) AS g.gidnumb, 
     g.id, 
     g.date, 
     't' AS isfirst 
    FROM cGift g 
    INNER JOIN (
     SELECT id, MIN(date) AS date 
     FROM cGift 
     GROUP BY id 
    ) f ON g.id = f.id AND g.date = f.date 
    GROUP BY g.id, g.date 
) first ON cGift.id = first.id AND cGift.date = first.date 

、最も内側のクエリは、前の溶液中でのように、すべての人のための最低限の日数を見つけ、しかし:は、あなたが唯一の寄付がtでマークしたい、あなたは、例えば、これを行うことができます特定のgidnumb値を持つリストについても詳細を示し、cGiftテーブルのこのリストと1人あたり1行だけ一致するようにします。

このクエリは、どのDBMSでも実行可能でなければなりません。二重のグループ分けを考えれば、それほど効率が悪いかもしれません。ここではまた、唯一の標準SQLを使用して代替が、何のベンダー固有の機能は、(それはまた、前のクエリよりも少し柔軟であるべきではありません)です。

SELECT 
    gidnumb, 
    id, 
    date, 
    CASE 
     WHEN NOT EXISTS (
      SELECT * 
      FROM cGift 
      WHERE id = g.id 
       AND (
        date < g.date OR 
        date = g.date AND gidnumb < g.gidnumb 
       ) 
     ) 
     THEN 't' 
    END AS isfirst 
FROM cGift g 

あなたが見ることができるように、isfirst列を使用して計算されますテーブルのセルフテスト:このテーブルに同じidとそれより前の日付の行がない場合、または同じ日付の場合はgidnumbより小さく、この行にはtとマークする必要があります。の一部がなく、CASEの部分には、ELSE NULLが含まれます。できれば、ELSE 'f'のようなものを追加してください。

しかし、SQL製品には、よりシンプルで効率的なクエリを構築することで恩恵を受ける可能性のある機能がある可能性があります。

SELECT 
    gidnumb, 
    id, 
    date, 
    CASE ROW_NUMBER() OVER (PARTITION BY id ORDER BY date, gidnumb) 
     WHEN 1 
     THEN 't' 
    END AS isfirst 
FROM cGift g 

:一部の製品は、例えば、ランキング機能をサポートここでは(あまりにもすでにSQL標準の一部であり、それは彼らが普遍的にまだサポートされていないだけということだ)、そしてあなたがROW_NUMBER()呼ばランキング機能で何ができるかですこのクエリは、それらをに分割し、最初にdate、次にgidnumbでソートする行をランク付けします。この場合のランクが1のすべての行は、tと区別する必要があります。

+0

ありがとう、これは完全にうまくいった – slicedtoad

+0

OK、1つは間違っていました。どうやら、同じ日に2回以上寄付をした人がいたため、複数のisfirst = 't'を持つ人々が生まれました。 min()の2番目の基準としてgidnumb(常にユニーク)を使用できますか?私は試みましたが、私はグループ化と結合に問題があります。注:gidnumbは必ずしも日付順ではないので、 'min(date)'の代わりに 'min(gidnumb)'だけを使うことはできません。 – slicedtoad

+0

@slicedtoad:私の更新を見てください。 –

1

質問にはエラーが表示されません。

ただし、クエリを少し修正することをおすすめします。

これはこれは、次の寄付今すぐUNIONを使用してそれをマージ

SELECT id, gidnymb, date, null AS new_column 
FROM cGift 
LEFT JOIN (
    SELECT id, gidnymb, date, "t" As new_column 
    FROM cGift 
    GROUP BY id 
    HAVING date = MIN(date) 
) USING(id) 
WHERE new_column IS NULL 

を返します。各ID

SELECT id, gidnymb, date, "t" As new_column 
FROM cGift 
GROUP BY id 
HAVING date = MIN(date); 

のための最初の寄付を返します。

(SELECT id, gidnymb, date, "t" As new_column 
FROM cGift 
GROUP BY id 
HAVING date = MIN(date)) 

UNION 

(SELECT id, gidnymb, date, null AS new_column 
FROM cGift 
LEFT JOIN (
    SELECT id, gidnymb, date, "t" As new_column 
    FROM cGift 
    GROUP BY id 
    HAVING date = MIN(date) 
) USING(id) 
WHERE new_column IS NULL) 

私はそれをテストしませんでしたが、あなたはそのアイディアを得ました。あなたが行うことができます2005+ SQL Serverで

+0

右の場合、having節の後にminを置くことができますが、それを完全に忘れてしまいます。これにより、はるかに簡単になります。 – slicedtoad

+0

私のプラットフォームであるかどうかは分かりませんが、これが変わるとエラーになります。私はAndriyのソリューションを使用しますが、ありがとう。 – slicedtoad

0

私は次のようにほとんどすべてのSQL製品で動作するはずだと思う。この

SELECT 
    gidnumb, 
    id, 
    Date, 
    CASE RANK() OVER (PARTITION BY id ORDER BY Date) 
     WHEN 1 Then 't' 
     ELSE Null 
    END 
FROM 
    cGift