44

別のタイトルは次のようになります: 複数行の存在を確認しますか?

SQL と C# の組み合わせを使用して、リスト内のすべての製品がテーブルに存在する場合、メソッドが true を返すようにします。すべてSQLで実行できる場合は、それが望ましいでしょう。productID次の SQL を使用して、シングルが存在するかどうかを返すメソッドを作成しました。

SELECT productID FROM Products WHERE ProductID = @productID

これが行を返す場合、c# メソッドは true を返し、それ以外の場合は false を返します。

今、私は製品 ID のリストを持っているかどうか疑問に思っています (通常は 20 未満の巨大なリストではありません)。すべての製品 ID が存在する場合は行を返し、1 つ以上の製品 ID が存在しない場合は行を返さないクエリを作成するにはどうすればよいですか?

(Maybe something involving "IN" like:
SELECT * FROM Products WHERE ProductID IN ('1', '10', '100', 'ABC'))

編集:

結果がどのように表現されるかは、私にとって重要ではありません。1クエリがや0、空の結果セットまたは空でない結果セットを返すかどうか、true または false は問題ではありません。1) 読みやすく、理解しやすく、2) パフォーマンスの高い回答を希望します。

製品IDのリストをSQLと連結することを想定していました。明らかに、これはコードを SQL インジェクションに開放します (製品 ID は実際にはvarchar. この場合、可能性はわずかですが、その可能性は避けたいと考えています)。したがって、これを回避する方法があれば、それはより良いでしょう。SQL Server 2005 を使用しています。

プロダクトIDはvarchar

4

14 に答える 14

30

更新された質問を考えると、これらは最も単純な形式です。

あなたProductIDが望むユニークな場合

SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100)

次に、その結​​果を、クエリしている製品の数と照合し3ます(この最後の部分は、SQLで実行できますが、SQLでさらに実行しない限り、C#で実行する方が簡単な場合があります)。

一意でない場合ProductID

SELECT COUNT(DISTINCT ProductID) FROM Products WHERE ProductID IN (1, 10, 100)

すべてProductIdsが存在し、それ以外の場合は行を返さないようにする必要があると考えられた場合:

SELECT ProductId FROM Products WHERE ProductID IN (1, 10, 100) AND ((SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100))=3)

また

SELECT ProductId FROM Products WHERE ProductID IN (1, 10, 100) AND ((SELECT COUNT(DISTINCT ProductID) FROM Products WHERE ProductID IN (1, 10, 100))=3)

あなたが実際に結果で何かをするつもりなら。SELECT 1 WHERE (SELECT ...)=3それ以外の場合は、他の回答が述べているか暗示しているように、単純なもので十分です。

于 2010-05-19T00:35:07.427 に答える
11

@Mark Hurd、エラーを指摘してくれてありがとう。

これは機能します (Postgresql、Sql Server 2008 を使用している場合):

create table products
(
product_id int not null
);



insert into products values(1),(2),(10),(100);

SELECT 
    CASE 
        WHEN EXISTS(
             SELECT 1 
             FROM (values(1),(10),(100)) as x(id) 
             WHERE x.id NOT IN (select product_id from products))
        THEN 0 --'NOT ALL'

        ELSE 1 -- 'ALL'
    END

MySQL を使用している場合は、一時メモリ テーブルを作成します (そこに 1,10,100 を入力します)。

create table product_memory(product_id int) engine=MEMORY;

insert into product_memory values(1),(10),(100);

SELECT 
    CASE 
        WHEN EXISTS(
             SELECT 1 
             FROM product_memory
             WHERE product_memory.id NOT IN (select product_id from products))
        THEN 0 -- 'NOT ALL'

        ELSE 1 -- 'ALL'
    END

C# コードで:

bool isAllExist = (int)(new SqlCommand(queryHere).ExecuteScalar()) == 1;

[編集]

すべての製品 ID が存在する場合は行を返し、1 つ以上の製品 ID が存在しない場合は行を返さないクエリを作成するにはどうすればよいですか?

すべての行が存在する場合は行 (単数)を返し、1 つ以上の製品 ID が存在しない場合は行は返されません。

MySql:

SELECT 1
WHERE 
    NOT EXISTS(
        SELECT 1
             FROM product_memory
             WHERE product_memory.id NOT IN (select product_id from products) )

Posgresql、Sql Server 2008:

SELECT 1
WHERE 
    NOT EXISTS(            
        SELECT 1 
        FROM (values(1),(10),(100)) as x(id) 
        WHERE x.id NOT IN (select product_id from products) )

次に、C# コードで次のようにします。

var da = new SqlDataAdapter(queryhere, connectionhere);
var dt = new DataTable();
da.Fill(dt);

if (dt.Rows.Count > 0) 
    return true; 
else 
    return false;

または、条件を短くするだけです。

return dt.Rows.Count > 0;
于 2010-05-19T02:19:15.887 に答える
1

SQL Serverを使用していると仮定すると、ブール型は存在しませんが、ビット型は存在します。これは、0または1のみを保持できます。0はFalseを表し、1はTrueを表します。

私はこのように行きます:

select 1
    from Products
    where ProductId IN (1, 10, 100)

ここでは、nullまたは行が返されません(行が存在しない場合)。

あるいは:

select case when EXISTS (
    select 1
        from Products
        where ProductId IN (1, 10, 100)
    ) then 1 else 0 end as [ProductExists]

ここでは、スカラー値1または0のいずれかが常に返されます(行が存在しない場合)。

于 2010-05-19T00:35:56.600 に答える
1
DECLARE @values TABLE (ProductId int)
INSERT @values (1)
INSERT @values (10)
INSERT @values (100)

SELECT CASE WHEN (SELECT COUNT(*) FROM @values v) = 
                 (SELECT COUNT(*) FROM Products p WHERE p.ProductId IN
                       (SELECT v.ProductId FROM @values v))
            THEN CAST(1 AS bit)
            ELSE CAST(0 AS bit)
       END [AreAllFound]
于 2010-05-19T06:01:48.307 に答える
0

IDを一時テーブルに格納している場合(これは、C#関数または単純なSQLで実行できます)、SQLで問題を簡単に実行できるようになります。

select "all exist"
where (select case  when count(distinct t.id) = (select count(distinct id) from #products) then "true" else "false" end
    from ProductTable t, #products p
    where t.id = p.id) = "true"

#productsこれは、ターゲットテーブル( )にすべての製品が存在する場合は「allexists」をProductTable返し、上記が当てはまらない場合は行を返しません。

一時テーブルに書きたくない場合は、検索しようとしている製品の数のパラメーターを入力し、一時テーブルを「in」に置き換える必要があります。句なので、サブクエリは次のようになります。

SELECT "All Exist"
WHERE(
        SELECT case when count(distinct t.id) = @ProductCount then "true" else "false" 
        FROM ProductTable t 
        WHERE t.id in (1,100,10,20) -- example IDs
) = "true"
于 2010-05-19T02:06:35.513 に答える
0

これは単純すぎるかもしれませんが、私は常に以下を使用します。

SELECT COUNT(*)>0 FROM `table` WHERE condition;
于 2011-11-23T13:01:41.767 に答える
0

C#は少しの作業(渡されたIDの数を数える)を行う必要がありますが、これを試してください:

select (select count(*) from players where productid in (1, 10, 100, 1000)) = 4

編集:

4は、整数のリストと同様に、確実にパラメーター化できます。

ユーザーが入力した文字列からSQLを生成していない場合は、攻撃について心配する必要はありません。もしそうなら、あなたはあなたが整数だけを取得することを確認する必要があります。たとえば、「1、2、3、4」という文字列を使用する場合は、次のようにします。

String.Join(",", input.Split(",").Select(s => Int32.Parse(s).ToString()))

あなたが間違ったことをした場合、それはスローされます。次に、それをパラメータとして設定します。

また、items.Count == 0の場合は、必ず特殊なケースを使用してください。送信するとDBがチョークするためwhere ParameterID in ()です。

于 2010-05-19T00:34:31.373 に答える
0
// not familiar with C#, but C#'s equivalent of PHP's:
$count = count($productIds); // where $productIds is the array you also use in IN (...)

SELECT IF ((SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100)) = $count, 1, 0)
于 2010-05-19T00:35:57.173 に答える
0

存在を確認しようとしている製品のリストはどこにありますか? そのリストが別のテーブル内に存在する場合、これを行うことができます

declare @are_equal bit
declare @products int

SELECT @products = 
     count(pl.id)
FROM ProductList pl
JOIN Products p
ON pl.productId = p.productId

select @are_equal = @products == select count(id) from ProductList

編集:

次に、すべての作業を C# で行います。アプリケーション内の製品の実際のリストをどこかにキャッシュし、LINQ クエリを実行します。

var compareProducts = new List<Product>(){p1,p2,p3,p4,p5};
var found = From p in GetAllProducts()
            Join cp in compareProducts on cp.Id equals p.Id
            select p;

return compareProducts.Count == found.Count;

これにより、手動で SQL クエリを作成することがなくなり、すべてのアプリケーション ロジックがアプリケーション内に保持されます。

于 2010-05-19T04:35:11.870 に答える
0

SQL Server 2008 を使用している場合は、テーブル値パラメーターを取るストアド プロシージャを作成します。クエリは、特に単純な形式にする必要があります。

CREATE PROCEDURE usp_CheckAll 
    (@param dbo.ProductTableType READONLY)
AS
BEGIN
    SELECT CAST(1 AS bit) AS Result
    WHERE (SELECT COUNT(DISTINCT ProductID) FROM @param)
        = (SELECT COUNT(DISTINCT p.ProductID) FROM @param AS p
           INNER JOIN Products 
               ON p.ProductID = Products.ProductID)
END

あなたが必要とするように、私は行を返すようにこれを変更しました。WHERE NOT EXISTS (ここで WHERE rhs IS NULL に LEFT JOIN を入力) を使用してこれを行う方法は他にもあります。

CREATE PROCEDURE usp_CheckAll 
    (@param dbo.ProductTableType READONLY)
AS
BEGIN
    SELECT CAST(1 AS bit) AS Result
    WHERE NOT EXISTS (
        SELECT * FROM @param AS p
        LEFT JOIN Products 
            ON p.ProductID = Products.ProductID
        WHERE Products.ProductID IS NULL
    )
END
于 2010-05-19T02:32:31.377 に答える
0

IN 句が (SP またはホットビルド SQL のいずれかへの) パラメータである場合、これはいつでも実行できます。

SELECT (SELECT COUNT(1)
          FROM product_a
         WHERE product_id IN (1, 8, 100)
       ) = (number of commas in product_id as constant)

IN 句がテーブルの場合、これはいつでも実行できます。

SELECT (SELECT COUNT(*)
          FROM product_a
         WHERE product_id IN (SELECT Products
                                FROM #WorkTable)
       ) = (SELECT COUNT(*)
              FROM #WorkTable)

IN 句が複雑な場合は、テーブルにスプールするか、2 回書き込みます。

于 2010-05-19T01:34:17.797 に答える