2017-07-17 5 views
1

C LINQクエリです:自分のIDがいくつかの値に等しい項目のリストを取得する - ここで#

from order in db.tblCustomerBuys 
where selectedProducts.Contains(order.ProductID) 
select order.CustomerID; 

selectedProductsすることは、たとえば、それは{ 1, 2, 3}で、一部の対象製品IDを含むリストです。 上記のクエリは、selectedProductsのいずれかを購入した顧客IDを返します。たとえば、誰かが製品1または2を購入した場合、そのIDが結果になります。

しかし、私はすべての製品を購入した顧客IDを収集する必要があります。たとえば、誰かが製品1と2と3を購入した場合、それは結果になります。

このクエリの編集方法は?

tblCustomerBuysはこのようなものです。このような

CustomerID - ID of Customer 
ProductID - the product which the customer has bought 

何か:更新

CustomerID  ProdcutID 
--------------------------- 
110    1 
110    2 
112    3 
112    3 
115    5 

:原因私はこのタイプを使用すべきいくつかの理由で、私はグループ化を行う必要があります答え、へ

クエリの:

var ID = from order in db.tblCustomerBuys 
     group order by order.CustomerID into g 
     where (selectedProducts.All(selProdID => g.Select(order => order.ProductID).Contains(selProdID))) 
     select g.Key; 

しかし、それはこのエラーを与えるでしょう: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.

+2

私はあなたがする必要があると思いますあなたのデータベースの構造も追加してください。 OrderとProductはどのように接続されていますか? –

+0

'tblCustomerBuys'の1つのエントリで、複数の製品の購入がどのように見えますか?これまでのところ、1つのフィールド 'ProductID'だけが表示されていますが、これは1つの値しか持たないことを前提としています。または私は間違っています –

+1

@MongZhu:これは、顧客と(購入した)prodcutsの関係テーブルです。したがって、「CustomerID」を繰り返すことは、この顧客が複数の商品を購入したことを意味します。 –

答えて

3

更新されたクエリは、問題の一般的なLINQソリューションです。

しかし、あなたのクエリプロバイダが(SQL IN (value_list)に翻訳され Contains以外)クエリ内のデータベーステーブルを持つメモリ内のシーケンスの混在をサポートしていないので、あなたはカウントすることができ All方法の代替同等のアプローチを必要とします(別個の)一致し、選択されたアイテム数と比較する。

{ CustomerID, ProductID }組み合わせがtblCustomerBuysで一意である場合は、次のようにクエリは次のようになります。

var selectedCount = selectedProducts.Distinct().Count(); 
var customerIDs = 
    from order in db.tblCustomerBuys 
    group order by order.CustomerID into customerOrders  
    where customerOrders.Where(order => selectedProducts.Contains(order.ProductID)) 
     .Count() == selectedCount 
    select customerOrders.Key; 

をそして、それが一意ではない場合は、次の基準を使用します。

where customerOrders.Where(order => selectedProducts.Contains(order.ProductID)) 
    .Select(order => order.ProductID).Distinct().Count() == selectedCount 
+1

良いコード、それは動作しますが、私は少し編集しました!あなたのコードには小さな問題があります: 'selectedProducts.Contains(order => order.ProductID)'を 'selectedProducts.Contains(order.ProductID)'に変更してください;) – Nofuzy

+0

典型的なSOエディターの入力ミス、申し訳ありません:) –

1

あなたはLinqの任意の条件を使用することができます。
ステップ1:あなたの質問が書き込まれると、そのリストから

List<int> selectedProducts = new List<int>() { 1,2 } // This list will contain required product ID 

db.tblCustomerBuys.where(o=> selectedProducts .Any(p => p == o.ProductID)).select (o=>o.order.CustomerID); // This will return all customerid who bought productID 1 or 2 
+0

ありがとう、しかし、私はproductID 1を買ったすべての顧客IDを返す必要があります 'AND' 2 – Nofuzy

3

を比較するために、LINQの任意の条件を使用し、それは少しある:すべての必要な製品IDが
ステップ2に格納されている場所int型のリストを作成します。あなたの構造を理解することは困難です。私が正しく理解していれば、いくつかのIDが含まれている列挙型selectedProductsがあります。 orderオブジェクトの列挙もあります。これらのオブジェクトは、私たちが気にかけている2つのプロパティ、ProductIdCustomerIdの整数です。この場合

、これは、ジョブを実行する必要があります。私たちはここでやっている

ver result = db.tblCustomerBuys.GroupBy(order => order.CustomerId) 
           .Where(group => !selectedProducts.Except(group).Any()) 
           .Select(group => group.Key); 

は、私たちが単一の値として各顧客を扱うことができるように、我々は、彼らのCustomerIdで一緒にすべての顧客をグループ化されています。次に、我々はselectedProductsのスーパーセットとしてgroupを扱い、一般的に使用されているlinqトリッキーを使用して、ある列挙が別の列挙のサブセットであるかどうかをチェックします。それに基づいてdb.tblCustomerBuysをフィルタリングし、一致する各注文のCustomerIdを選択します。

関連する問題