2009-06-05 9 views
2

を異なった行、私はこの(簡潔にするため省略無関係なフィールド)のような構造のデータベーステーブルを持っている検索:すべてのフィールドは整数ですSQL:フィールド値は

rankings 
------------------ 
(PK) indicator_id 
(PK) alternative_id 
(PK) analysis_id 
rank 

を。最初の3つ(「(PK)」と表示されています)は複合主キーです。与えられた「分析」には複数の「選択肢」があり、それぞれには多くの「インジケータ」ごとに「ランク」があります。

代替/インジケータの組み合わせのランクが異なる任意の数の分析を効率的に比較する方法を探しています。我々は、このデータ持っているのであれば、例えば、:

analysis_id | alternative_id | indicator_id | rank 
---------------------------------------------------- 
      1 |    1 |   1 | 4 
      1 |    1 |   2 | 6 
      1 |    2 |   1 | 3 
      1 |    2 |   2 | 9 
      2 |    1 |   1 | 4 
      2 |    1 |   2 | 7 
      2 |    2 |   1 | 4 
      2 |    2 |   2 | 9 

を...そして、理想的な方法は、以下の違いを識別します:

analysis_id | alternative_id | indicator_id | rank 
---------------------------------------------------- 
      1 |    1 |   2 | 6 
      2 |    1 |   2 | 7 
      1 |    2 |   1 | 3 
      2 |    2 |   1 | 4 

私は私が何をしたいんクエリを思い付い2つの解析IDの間に違いがあることがわかりました(つまり、ユーザーが2、5、9などを比較したい場合や、少なくとも1つの解析他のものとは異なる)。私のクエリは次のとおりです。

declare @analysisId1 int, @analysisId2 int; 
select @analysisId1 = 1, @analysisId2 = 2; 

select 
    r1.indicator_id, 
    r1.alternative_id, 
    r1.[rank] as Analysis1Rank, 
    r2.[rank] as Analysis2Rank 
from rankings r1 
inner join rankings r2 
    on r1.indicator_id = r2.indicator_id 
     and r1.alternative_id = r2.alternative_id 
     and r2.analysis_id = @analysisId2 
where 
    r1.analysis_id = @analysisId1 
    and r1.[rank] != r2.[rank] 

(これは、追加のフィールドの代わりに、列に分析値を置く、私はどちらかの方法が働くだろうと思います。。)

どのように私は多くの分析IDを処理するために、このクエリを一般化することができますか? (あるいは、別のより良いクエリを出して仕事をしていますか?)重要な場合に備えて、SQL Server 2005を使用しています。

必要に応じて、私はいつもテーブルからすべてのデータを取り出してコードの違いを探すことができますが、しばしば何千もの行が気になることが多いのでSQLソリューションが望ましいでしょう。私がそれを避けることができれば、それらをすべて転送する。 (ただし、SQLでこれを行わないような魅力的な理由がある場合は、これも良い答えと考えています)

答えて

2

これは、あなたの希望のデータセットを返します - 今、あなただけのクエリに必要な分析IDを渡す方法が必要です。または、アプリケーション内でこのデータをフィルタリングするだけでも可能です。

select r.* from rankings r 
    inner join 
    (
     select alternative_id, indicator_id 
     from rankings 
     group by alternative_id, indicator_id 
     having count(distinct rank) > 1 
    ) differ on r.alternative_id = differ.alternative_id 
    and r.indicator_id = differ.indicator_id 
    order by r.alternative_id, r.indicator_id, r.analysis_id, r.rank 
+0

パーフェクト - 一時テーブルなしでそれをするためのボーナスポイント!ありがとう! –

1

使用しているデータベースがSQL Server Iこのように行くだろう:

-- STEP 1, create temporary table with all the alternative_id , indicator_id combinations with more than one rank: 
select alternative_id , indicator_id 
into #results 
from rankings 
group by alternative_id , indicator_id 
having count (distinct rank)>1 

-- STEP 2, retreive the data 

select a.* from rankings a, #results b 
where a.alternative_id = b.alternative_id 
and a.indicator_id = b. indicator_id 
order by alternative_id , indicator_id, analysis_id 

ところで、ここで与えられた他の答えは、カウント(個別のランク)が必要です!!!!!

+0

これは私が求めていたものです - ありがとう!私はダンに断言の表を付けずにそれを引き出すためにノーを与えなければなりません。 ;-) –

+0

ああ、私は一時テーブルが大好き!それについて申し訳ありません:-) – tekBlues

0

私は、これはあなたが何をしようとしてあると思う:

select 
    r.analysis_id, 
    r.alternative_id, 
    rm.indicator_id_max, 
    rm.rank_max 
from rankings rm 
    join (
     select 
      analysis_id, 
      alternative_id, 
      max(indicator_id) as indicator_id_max, 
      max(rank) as rank_max 
     from rankings 
     group by analysis_id, 
      alternative_id 
     having count(*) > 1 
    ) as rm 
    on r.analysis_id = rm.analysis_id 
    and r.alternative_id = rm.alternative_id 
0

あなたの例の違いは間違っているようです。 の代替/インジケータの組み合わせのランクがであるが、例の行3と4がこの基準を満たさない分析が必要だとします。あなたの条件に応じて、正しい結果は次のとおりです。クエリに

analysis_id | alternative_id | indicator_id | rank 
---------------------------------------------------- 
     1 |    1 |   2 | 6 
     2 |    1 |   2 | 7 
     1 |    2 |   1 | 3 
     2 |    2 |   1 | 4 

あなたは試みることができるこのです:

with distinct_ranks as (
    select alternative_id 
    , indicator_id 
    , rank 
    , count (*) as count 
    from rankings 
     group by alternative_id 
     , indicator_id 
     , rank 
    having count(*) = 1) 
select r.analysis_id 
    , r.alternative_id 
    , r.indicator_id 
    , r.rank 
from rankings r 
    join distinct_ranks d on r.alternative_id = d.alternative_id 
     and r.indicator_id = d.indicator_id 
     and r.rank = d.rank 

あなたが持っている基準があいまいで、複数の分析にそれを実現する必要があります。分析1,2および3がランク1を有し、4,5および6が代替/インジケータ1/1についてランク2を有する場合はどうなるか?セット(1,2,3)はセット(4,5,6)と「異なっていますが、各セットの中には違いはありません。あなたがそのような場合にあなたが望む行動は、彼らが現れるかどうかですか?私のクエリは、他のすべての分析から同じ代替/インジケータ*のランクが異なるすべてのレコードを検索しますが、これが要件に合っているかどうかは不明です。

+0

あなたは正しいです、例は欠陥がありました - 私のタイプミスは修正されました。それをキャッチするためにありがとう。 任意の組み合わせの解析IDをこのクエリに渡して、ランクが異なる行を返すようにします。したがって、あなたの例では、セット(1,2,3)を渡すと、行は返されません。同様に私が(4,5,6)を渡した場合。しかし、私が(1,4)を通過すれば、それは異なるランクを返すだろう。 DanとtekBluesの回答は、特定の解析IDを渡すアカウントを若干修正した後、私の希望する振る舞いを反映しています。 –

+0

(1,2,4,5)はすべて返されますか? –

+0

はい、そうです。 –