2011-07-12 5 views
3

1から4の変数を渡すことができるストアドプロシージャがあり、最も列が一致する行を返す必要があります。ヌルです)。 シーケンスは異なる必要があります。データとSQL Serverは、ほとんどの列が一致する場所を選択します。

例テーブル:

Client_Id Project_ID Phase Task Employee Sequence 
--------- ---------- ----- ---- -------- -------- 
NULL  NULL  NULL NULL Chris 1 
NULL  NULL  NULL NULL Bob  100 
500  NULL  NULL NULL Joe  1 
500  2   NULL NULL Max  1 

ように、クライアント100の結果は、任意のプロジェクト、フェーズまたはタスクには、単にクリスとボブのデフォルトのNULLレコードになります。クライアント500の場合、結果はJoeとBobになります。クライアント500、プロジェクト2の場合、結果はMaxとBobになります。 今、私はこの質問を、最初にタスクをチェックし、それをフェーズごとにクエリに参加させ、どの行も重複していないことを確認して、プロジェクトとクライアントのために同じことを行うことによって行っています。それは信じられないほど非効率的で、このことについてよりスマートな方法が必要です。何かご意見は?

EDIT - いくつかのクエリ例、私はすべてが

insert into #TempTracking 
    select p.employee, p.sequence 
     from  invoices i, projects p 
     where i.client_id = p.client_id 
     and  i.project_no = p.project_no 
     and  i.phase = p.phase 
     and  i.task = p.task 

と一致した場合の最初のチェックそれから私は、クエリが少なく、特定作り、シーケンスが既に存在していないことを確認してください。

insert into #TempTracking 
select p.employee, p.sequence 
    from  invoices i, projects p 
    where (i.client_id = p.client_id or i.client_id is null) 
    and  (i.project_no = p.project_no or i.project_no is null) 
    and  (i.phase = p.phase or i.phase is null) 
    and  (i.task = p.task or i.task is null) 
    and  NOT EXISTS (SELECT * FROM #TempTracking t WHERE t.sequence = p.sequence) 
+0

どのバージョンのSQL Serverですか? – Matthew

+0

'Client 500の場合、Project 2の結果はMaxとBobです.'Maxを返すだけでいいですか? –

+0

Abeは良い点を挙げています.BobはClient 500、Project 2ではどのように有効な結果をもたらしましたが、Chrisはそうではありませんか? – Seph

答えて

3

は、「列のほとんどが一致し、」非常にあいまいですが、私はあなたが彼らがnullを検索、またはテーブル内の値がnullの場合、このレコードを前提とした場合に含まれ得ることを意味すると仮定します。

あなたが最も一致する行または何も一致しないすべての行をしたい場合は、あなたがこのような何かを行う必要がありますが(非常に長い取得し始めています)

DECLARE @Client_Id VARCHAR(MAX) = '500' 
DECLARE @Project_ID VARCHAR(MAX) = '2' 
DECLARE @Phase VARCHAR(MAX) = NULL 
DECLARE @Task VARCHAR(MAX) = NULL 

SELECT Employee, Sequence 
FROM 
    (SELECT Employee, Sequence, 
    (
    CASE WHEN (Client_Id = @Client_Id OR Client_Id IS NULL OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Project_ID = @Project_ID OR Project_ID IS NULL OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Phase = @Phase OR Phase IS NULL OR @Phase IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Task = @Task OR Task IS NULL OR @Task IS NULL) THEN 1 ELSE 0 END 
) AS MatchCount 
WHERE MatchCount = 
    (
    SELECT MAX(
     CASE WHEN (Client_Id = @Client_Id OR Client_Id IS NULL OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Project_ID = @Project_ID OR Project_ID IS NULL OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Phase = @Phase OR Phase IS NULL OR @Phase IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Task = @Task OR Task IS NULL OR @Task IS NULL) THEN 1 ELSE 0 END 
    ) 
    FROM myTable 
) 
    -- Now prevent for duplicate sequence numbers 
    AND NOT EXISTS (
    SELECT Employee, Sequence 
    FROM 
     (SELECT Employee, Sequence, 
     (
     CASE WHEN (Client_Id = @Client_Id OR Client_Id IS NULL OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Project_ID = @Project_ID OR Project_ID IS NULL OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Phase = @Phase OR Phase IS NULL OR @Phase IS NULL) THEN 1 ELSE 0 END + 
     CASE WHEN (Task = @Task OR Task IS NULL OR @Task IS NULL) THEN 1 ELSE 0 END 
    ) AS MatchCount 
     FROM myTable) mt2 
    WHERE mt2.MatchCount = 
     (
     SELECT MAX(
      CASE WHEN (Client_Id = @Client_Id OR Client_Id IS NULL OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
      CASE WHEN (Project_ID = @Project_ID OR Project_ID IS NULL OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
      CASE WHEN (Phase = @Phase OR Phase IS NULL OR @Phase IS NULL) THEN 1 ELSE 0 END + 
      CASE WHEN (Task = @Task OR Task IS NULL OR @Task IS NULL) THEN 1 ELSE 0 END 
     ) 
     FROM myTable 
    ) 
     AND mt2.Sequence = myTable.Sequence AND mt2.MatchCount > myTable.MatchCount 
) 

注:これは、内のすべてのレコードを返します。一致するフィールドの数がゼロのときのテーブル

私はかなりのクエリを減らすことによって、彼らは、これは一時テーブルに一致するすべての行を挿入し、(MatchCount)と一致した列の数などによってそれほど冗長にならないためにクリーンアップすることができな方法ですしていることを確認そこです。あなたはユニークな配列と最も高い一致列/行をしたいので、

さて、あなたが探している結果を返されるより、このような:

DECLARE @Client_Id VARCHAR(MAX) = '500' 
DECLARE @Project_ID VARCHAR(MAX) = '3' 
DECLARE @Phase VARCHAR(MAX) = NULL 
DECLARE @Task VARCHAR(MAX) = NULL 

INSERT INTO #myTempTable SELECT Employee, Sequence, 
    (
    CASE WHEN (Client_Id = @Client_Id OR Client_Id IS NULL OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Project_ID = @Project_ID OR Project_ID IS NULL OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Phase = @Phase OR Phase IS NULL OR @Phase IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Task = @Task OR Task IS NULL OR @Task IS NULL) THEN 1 ELSE 0 END 
) AS MatchCount, 
    (
    CASE WHEN (Client_Id IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Project_ID IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Phase IS NULL) THEN 1 ELSE 0 END + 
    CASE WHEN (Task IS NULL) THEN 1 ELSE 0 END 
) AS NullCount 
-- ,(
-- CASE WHEN (Client_Id = @Client_Id OR @Client_Id IS NULL) THEN 1 ELSE 0 END + 
-- CASE WHEN (Project_ID = @Project_ID OR @Project_ID IS NULL) THEN 1 ELSE 0 END + 
-- CASE WHEN (Phase = @Phase OR @Phase IS NULL) THEN 1 ELSE 0 END + 
-- CASE WHEN (Task = @Task OR @Task IS NULL) THEN 1 ELSE 0 END 
-- ) AS MatchCountWithoutNulls 

SELECT Employee, Sequence 
FROM #myTempTable mtt 
WHERE MatchCount = (
    SELECT MAX(MatchCount) 
    FROM #myTempTable mtt2 
    WHERE mtt2.Sequence = mtt.Sequence 
) 
    AND NullCount = (
    SELECT MIN(NullCount) 
    FROM #myTempTable mtt2 
    WHERE mtt2.Sequence = mtt.Sequence 
) 

またはそれに非常に近いもの、私は「ドンテストテーブルを持っているので、私はそれを蹴って見ることができません。

+0

それは曖昧で、私は謝罪します。私はその解決方法を知っていますが、特定の問題を明確にするのは難しいです。 – ChrisOPeterson

+0

それは大丈夫です、私はあなたが明言しようとしていることを理解していると思います...私の最新の編集を見て、それはあなたが探しているものでなければなりません – Seph

関連する問題