2011-01-24 4 views
0

に基づいてこれはこのフォーラムで私の最初の投稿です、私は確かに達人からいくつかの助けを得ることを期待:)マッチSQL列ユーザー入力

私が達成しようとしていますどのような7列は私のdbテーブルにあるということです。 1つは主キーであり、残りの6つは整数列です。これで私のアプリケーションでは6つの値を入力できます。ユーザーが入力した6つの値を6つの整数列と比較し、いずれかの行に3つ以上の列がユーザーの入力と一致するようにしたいと考えています。私はまだ私の結果を達成することができません..

助けていただければ幸いです!

おかげ

DBテーブルの構造を更新し

は..私は2,3,7,11,45,65を入力しています。返される行数は

UID A1 A2 A3 A4 A5 A6 
----------------------- 
1 2 3 4 5 6 7 
2 2 3 4 55 56 57 
3 65 11 45 66 67 68 
4 45 7 11 99 98 97 
5 7 7 7 7 7 7 
6 7 7 7 7 7 7 
7 8 8 8 8 8 8 
8 8 8 8 8 8 8 
9 45 45 0 3 1 2 
10 65 7 4 0 0 0 

IDが1,3,4,9,10

+0

どのようにプライマリキーを生成していますか? –

+0

重要な質問:入力を対応する列(結合ロック)に一致させようとしていますか、または入力がどの列にも一致することはできますか?言い換えれば、1,2,3,4,5,6が6回、5回、4回、7回、7回、3回または0回繰り返すのでしょうか? また、重複した番号が許可されていますか、これはもっとキノの問題のようですか? – nycdan

+0

任意の入力は、db内の任意の列に一致する可能性があります。 – mumair

答えて

1

あなたが値を反復処理し、比較基準を満たす列ごとに変数にを追加することができなければなりません返さ。5.例えばなければなりません。列に(MSDNピボット例から)

DECLARE @Accumulator int 
DECLARE @Threshold int 
DECLARE @ReturnValue int 

DECLARE @PK int 
DECLARE @Col1 int 
DECLARE @Col2 int 
DECLARE @Col3 int 
DECLARE @Col4 int 
DECLARE @Col5 int 
DECLARE @Col6 int 

DECLARE @UserInput1 int 
DECLARE @UserInput2 int 
DECLARE @UserInput3 int 
DECLARE @UserInput4 int 
DECLARE @UserInput5 int 
DECLARE @UserInput6 int 

-- Assuming you would set each @UserInputx above to a value input by the user... 

SET @Accumulator = 0 
SET @Threshold = 3 
SET @ReturnValue = 0 

SELECT 
    @PK = PrimaryKey, 
    @Col1 = Col1, 
    @Col2 = Col2, 
    @Col3 = Col3, 
    @Col4 = Col4, 
    @Col5 = Col5, 
    @Col6 = Col6 
FROM TheTable 

IF @Col1 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Col2 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Col3 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Col4 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Col5 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Col6 IN (@UserInput1, @UserInput2, @UserInput3, @UserInput4, @UserInput5, @UserInput6) 
    SET @Accumulator = @Accumulator + 1 

IF @Accumulator >= 3 
    SET @ReturnValue = @PK 
+0

は0行を返します。それも変更しようとしましたが、使用しませんでした! – mumair

2

ダミーデータ

CREATE TABLE Mytable (PK int, col1 int, col2 int, col3 int, col4 int, col5 int, col6 int) 
GO 
INSERT INTO Mytable VALUES (1, 1,4,3,5,4,4) 
INSERT INTO Mytable VALUES (2, 2,4,1,5,5,5) 
INSERT INTO Mytable VALUES (3, 3,4,3,5,4,4) 
INSERT INTO Mytable VALUES (4, 4,4,2,5,5,4) 
INSERT INTO Mytable VALUES (5, 5,5,1,5,5,5) 
GO 

入力データ

DECLARE @MyInput TABLE (InputValue int) 
INSERT @MyInput VALUES (2) 
INSERT @MyInput VALUES (4) 
INSERT @MyInput VALUES (5) 

UNPIVOTソース列データ:

このようなものを。今、私たちは、大規模なOR句

SELECT 
    * 
FROM 
    myTable MT2 --effectively PIVOT back to get original rows 
    JOIN 
    (
    SELECT 
     PK 
    FROM --7 columns into 3, make column name a row identifier 
     (SELECT PK, col1, col2, col3, col4, col5, col6 FROM myTable) MT 
     UNPIVOT 
     (colvalue FOR RowNumber IN (col1, col2, col3, col4, col5, col6)) cols 
     JOIN --match to user input, set based 
     @MyInput MD ON cols.colvalue = MD.InputValue 
    GROUP BY 
     PK --per original row 
    HAVING 
     COUNT(DISTINCT MD.InputValue) >= 3 
    ) foo ON MT2.PK = foo.PK 

せずに、我々は3つの試合を持っている場所を見つけるために、JOINと集約することができますこれは、私は、これはする最も簡単なことだと思う、セット2、4のために働く5と1、4、5

0

実装する

SELECT ID 

from TABLE 

WHERE 

CASE WHEN integerCol1 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END + 
CASE WHEN integerCol2 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END + 
CASE WHEN integerCol3 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END + 
CASE WHEN integerCol4 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END + 
CASE WHEN integerCol5 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END + 
CASE WHEN integerCol6 IN 
(@user1,@user2,@user3,@user4,@user5,@user6) THEN 1 ELSE 0 END >=3 
+0

El Ronnoco、私はそれが間違って返すSQLクエリを使用するのが疲れました。それはすべての6つの列に同じ文字を持つ行を返します。そして返されるべき2つの列を逃します – mumair

+0

@ user587619ああ、私の間違い。 3つの列にユーザー入力のいずれかが含まれている場合のみです。 3つの列が一意であるかどうかはチェックしません... –

+0

@ user587619しかし、なぜ返されない行が返されないのかわかりません... –

0

私はコードを書く時間がありませんが、ネストされたループを試したと言われました。あなたがしたいことを理解したので、少なくとも私はあなたのために働くと思う方向にあなたを与えることができます。

インナーループでは、入力を比較したい最初のリストを取得し、入力の最初を取得し、一致または最後に達するまでリストの各メンバーと比較します。今は難しい部分です...リストの同じメンバーに入力の2番目の数字を2回一致させたくないので(たとえば2 7秒を入力した場合)、一致したメンバーを違法な番号に変更する必要があります。正の数だけが許可されている場合は、-1に変更します。これは、あなたがそれに2度マッチしないようにします。

私たちのミドルループでは、完了するまで残りの入力番号を同じリストに対して処理します。一致を判断するには、そのリスト内の出現回数-1(または一致を示すために使用するもの)をカウントすると、成功/失敗インジケータが表示されます。

外側のループでは、同じ方法で各リストを確認してください。非常に粗い擬似コードで

:和[L]> = 3で一致する

var x = set of all lists 
foreach (list l in x) //go through each list 
{ 
foreach (item i in inputlist) //go through each item in your input 
    { 
    foreach (item j in l) //compare to each item in the current list 
     { 
     if (i = j) 
      { 
       j = -1; //set matched item to -1 to avoid rematching 
       sum[l]++; 
      } 
     } 
    } 
} 

完全な、任意のリスト。

+0

あなたのアプローチはやや似ています: ) – mumair

0

まあおかげ応答のための誰もが、それはどちらも私を助け:Pは

入れ子のは周りの行のを連結したあなたに合ったどんなデータセットまたはGridViewの...

私はそれを回した道を経由するループすべての列の値は、行に1 2 3 4 5 6値があるように、特殊文字を含みます。[1] [2] [3] [4] [5] [6]になり、.Contains関数値が使用されている場合はそれを比較する.Replaceは文字列から除外し、ループがインクリメントされたときにカウントされないことを確認します..

古典的なアプローチです。

ありがとうございました:)