0

問題

SQL Serverでストアドプロシージャを作成して、最も一致するレコードを見つけようとしています。テーブルの5つの列A、B、C、D、およびEに対応する5つの入力パラメーター@ A、@ B、@ C、@ D、および@E(すべてvarchar50)が与えられた場合、最も一致する列で記録します。選択したレコードで一致しない各列には、スペース''が含まれている必要があります。

たとえば、「Sony」、「PlayStation」、「Controller」、「Black」、「Damaged」という入力があり、テーブルに次の列が含まれている場合:

"Sony"  "Playstation"  "Unit"   "Black"  "Damaged"
"Sony"  "Playstation"  " "      " "      " "

2つのパラメーターが一致し、一致しない3つのパラメーターにはスペースがあるため、2番目の行を返す必要があります。4つのパラメーターが一致していても、真ん中のパラメーターが一致せず、スペースではないため、最初の行を返したくありません。スペースだったら、最初の列が勝者だったでしょう。

私のアプローチ

明らかにできないさまざまな詳細がありますが、私の基本的なアプローチ(私はSQL初心者であることに注意してください)は、MOST固有からLEAST固有までのすべての組み合わせをテストすることでした。したがって、私のクエリは次のようになります。

-- start with most specific
SELECT * FROM dbo.Items WHERE
   A = @A
   B = @B
   C = @C
   D = @D
   E = @E

-- if no matches, try next
IF @@ROWCOUNT = 0
SELECT * FROM dbo.Items WHERE
   A = @A
   B = @B
   C = SPACE(1)
   D = @D
   E = @E

... etc.

私の場合、順列の一部は存在しないため、実際にテストする必要があるのは16の構成だけです。それでも、これは私が望むことを達成するための非常に非効率的な方法のようです。その上、それも機能していません。自動トリミングが行われているため、スペースとの比較には問題があるようです。いずれにせよ、私の現在のアプローチは非効率的で機能しないようです-それで私はあなたに助けを求めます。

4

3 に答える 3

2

このようなもの?

-- Temp table to play with
SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '

-- The query
DECLARE @a nvarchar(50), @b nvarchar(50), @c nvarchar(50), @d nvarchar(50), @e 

nvarchar(50)
SET @a = 'Sony'
SET @b = 'Playstation'
SET @c = 'Controller'
SET @d = 'Black'
SET @e = 'Damaged'

SELECT TOP 1 I.*
FROM (
    SELECT ID,
        CASE WHEN @a = a THEN 1 WHEN a = ' ' THEN 0 ELSE NULL END AS AResult,
        CASE WHEN @b = b THEN 1 WHEN b = ' ' THEN 0 ELSE NULL END AS BResult,
        CASE WHEN @c = c THEN 1 WHEN c = ' ' THEN 0 ELSE NULL END AS CResult,
        CASE WHEN @d = d THEN 1 WHEN d = ' ' THEN 0 ELSE NULL END AS DResult,
        CASE WHEN @e = e THEN 1 WHEN e = ' ' THEN 0 ELSE NULL END AS EResult
    FROM #Items
) IW
INNER JOIN #Items I ON I.ID = IW.ID
WHERE AResult IS NOT NULL AND BResult IS NOT NULL AND CResult IS NOT NULL 
    AND DResult IS NOT NULL AND EResult IS NOT NULL
ORDER BY AResult + BResult + CResult + DResult + EResult DESC

これにより、次の値が返されます。

"Sony"  "Playstation"  " "      " "      " "

私が遊んだ一時テーブルをこれに変更すると、次のようになります。

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, ' ' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '

次に、取得する必要があります

"Sony"  "Playstation"  " "   "Black"  "Damaged"

そして最後に、一時テーブルの例にこれがある場合:

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', 'Unit', ' ', ' '

どちらも3番目の列に「Unit」があるため、何も返されません。

于 2012-08-24T17:46:28.327 に答える
1

5つの比較(列AE間)のそれぞれにスコアを付けてから、スコアを合計します。

いずれかの行でcolA=colAの場合、スコアは1になります。

colA <>colAおよび2行目のcolA=''の場合、スコアは0です。

残りの行はスコアリングされないままにします(colAのスコアのnull値)

最適な一致は、どの列にもnullスコアがなく、最高のスコアになります。

わかる?

列のスコアを設定するための更新ステートメントの例を次に示します。

update table
set scoreAcol = scoreA, scoreAcol = scoreB, scoreCcol = scoreC, scoreDcol = scoreD, scoreEcol = scoreE
from
    (select
    case when cola = @a then 1 when cola= ' ' then 0 end as scoreA,
    case when colb = @b then 1 when colb= ' ' then 0 end as scoreb,
    case when colc = @c then 1 when colc= ' ' then 0 end as scorec,
    case when cold = @d then 1 when cold= ' ' then 0 end as scored,
    case when cole = @e then 1 when cole= ' ' then 0 end as scoree) s
from table

再度スコアを付ける前に、null以外のすべてのスコアをnullに設定すると想定しています。

行のスコアを合計するには、

update table set score = scoreAcol + scoreBcol + scoreCcol + scoreDcol + scoreEcol 

null値を指定すると、score値がnullになります。次に、スコアの高い一致を見つけるために、score降順で並べ替えることができます。

于 2012-08-24T17:31:46.750 に答える
0

SQl Serverでは、CTEとNullifを次のように使用できます(テストされていません)

declare @a int = 1
, @B int = 2
, @c int= 3
, @d int= 4
, @E int- 5

; counts(id、ACount、BCount、CCount、DCount、ECount)AS(select id、sum(case when A = @a or nullif(a、'')is null then 1 else 0 end)as ACount、sum( b = @bまたはnullif(b、'')がnullの場合は1 else 0 end)as bCount、sum(c = @cまたはnullif(c、'')がnullの場合は1 else 0 end)as cCount、sum(d = @dまたはnullif(d、'')がnullの場合は1、それ以外の場合は0 end)as dCount、sum(e = @eまたはnullif(e、''の場合)がnullの場合は1 else 0終了)dbo.itemsからのeCountとして)

、totals(id、Totalcount)AS(select id、max(ACount + BCount + CCount + DCount + ECount)as totalCount from counts where Acount <> 0 and BCount <> 0 and CCount <> 0 and DCount <> 0 And ECount <> 0 group by id)

i.id、ia、ib、ic、idを選択します。つまり、dbo.itemsからi.id = t.idの合計tに参加します。もちろん、パラメーターは実際の定義が何であれ、

于 2012-08-24T17:52:41.217 に答える