3

以下の(少し複雑な)バージョンの手順があります。

CREATE PROC sp_Find_ID (
    @Match1 varchar(10),
    @Match2 varchar(10)
) AS

DECLARE @ID int

SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
    AND Coalesce(Match2,@Match2,'') = Coalesce(@Match2,Match2,'')

SELECT @ID ID

基本的に、Match1 は必須の一致ですが、Match2 はプロシージャへの入力と検索対象のテーブルの両方でオプションです。2 番目の一致は、入力および/またはテーブルの Match2 値が null である場合、または両方が同じ (null ではない) 値である場合に成功します。

私の質問は次のとおりです。これを行うためのより効率的な(またはさらに読みやすい)方法はありますか?

私はこの方法を数回使用しましたが、毎回少し汚れているように感じます (主観的な汚れは認めます)。

4

5 に答える 5

4

これを行うためのより効率的な(またはさらに読みやすい)方法はありますか?

COALESCE/etc を使用して提供した例は、non-sargableです。クエリに存在する必要があるものだけが実行されるように、物事を分離する必要があります。

DECLARE @ID int

IF @Match2 IS NOT NULL
BEGIN

  SELECT @ID = t.id
    FROM TABLE1 t
   WHERE t.match1 = @Match1
     AND (t.match2 = @Match2 OR t.match2 IS NULL)

END
ELSE
BEGIN

  SELECT @ID = t.id
    FROM TABLE1 t
   WHERE t.match1 = @Match1

END

SELECT @ID ID

これを単一の SQL ステートメントで実行したい場合は、動的 SQL が唯一の現実的な代替手段です。さらに読む前に、動的 SQL の呪いと祝福を読むことを強くお勧めします。

DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = N' SELECT @ID = t.id
                    FROM TABLE1 t
                   WHERE t.match1 = @Match1 '

    SET @SQL = @SQL + CASE 
                        WHEN @Match2 IS NOT NULL THEN
                          ' AND (t.match2 = @Match2 OR t.match2 IS NULL) ' 
                        ELSE 
                          ' '
                      END

BEGIN

  EXEC sp_executesql @SQL,
                     N'@ID INT OUTPUT, @Match1 VARCHAR(10), @Match2 VARCHAR(10)',
                     @ID, @Match1, @Match2

END
于 2010-09-29T17:20:10.857 に答える
4

OR や ISNULL などの回避

  • いずれかの側が NULL の場合、EXCEPT ビットは行を返しません
  • Match2 <> @Match2 は、NULL 以外の不一致を除外することを意味します

このようなもの

DROP TABLE dbo.Table1

CREATE TABLE dbo.Table1 (ID int NOT NULL, Match1 int NOT NULL, Match2 int NULL)
INSERT dbo.Table1 VALUES (1, 55, 99), (2, 55, NULL)

DECLARE @Match1 int = 55, @Match2 int

SELECT ID
FROM
    (
    SELECT ID FROM Table1 WHERE Match1 = @Match1
    EXCEPT -- @Match2 = NULL, match both rows (99, NULL)
    SELECT ID FROM Table1 WHERE Match2 <> @Match2
    ) foo

SET @Match2 = -1
SELECT ID
FROM
    (
    SELECT ID FROM Table1 WHERE Match1 = @Match1
    EXCEPT -- @Match2 = -1, match ID = 2 only where Match2 IS NULL
    SELECT ID FROM Table1 WHERE Match2 <> @Match2
    ) foo
于 2010-09-29T17:33:31.840 に答える
1

これがもっと好ましいかどうかわからない。

SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
    AND ((Match2 = @Match2) OR Coalesce(Match2,@Match2) IS NULL)
于 2010-09-29T17:07:13.000 に答える
0

私はこれがそれを行うべきだと思っていたでしょう-それがオプションであるならば@Match2値がそうなるという条件で。NULL

CREATE PROC sp_Find_ID (
    @Match1 varchar(10),
    @Match2 varchar(10)
) AS

DECLARE @ID int

SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
    AND Match2 = IsNull(@Match2, Match2)

SELECT @ID ID 
于 2010-09-29T17:07:12.920 に答える
0

私には簡単に見えますか?私は何かが欠けているに違いない..合体は必要ない

SELECT @ID = ID
 FROM Table1
 WHERE Match1 = @Match1
    AND (
          (Match2 is null and  @Match2 is null)
           or
           @Match2=Match2
    )

SELECT @ID ID
于 2010-09-29T17:03:08.653 に答える