Как получить ProductIds путем поиска нескольких свойств в SQL или Linq To Sql? - PullRequest
3 голосов
/ 27 июня 2011

Существует две таблицы: Product, ProductProperty

ProductProperty - это таблица, в которой хранятся InfoKey и InfoValue продуктов.

SQLПример сценария:

CREATE TABLE [dbo].[ProductProperty](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ProductId] [int] NOT NULL,
    [InfoKey] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
    [InfoValue] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
 CONSTRAINT [PK_ProductProperty] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
)

GO

SET IDENTITY_INSERT [dbo].[ProductProperty] ON
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (1, 1, N'k1', N'v1')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (3, 2, N'k1', N'v1')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (4, 3, N'k1', N'v2')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (6, 5, N'k1', N'v1')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (7, 2, N'k2', N'v1')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (8, 1, N'k2', N'v1')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (9, 5, N'k2', N'v2')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (10, 2, N'k3', N'v2')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (11, 3, N'k3', N'v2')
INSERT [dbo].[ProductProperty] ([Id], [ProductId], [InfoKey], [InfoValue]) VALUES (12, 5, N'k3', N'v1')
SET IDENTITY_INSERT [dbo].[ProductProperty] OFF

GO

CREATE TABLE [dbo].[Product](
    [ProductId] [int] IDENTITY(1,1) NOT NULL,
    [ProductName] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
 CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED 
(
    [ProductId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
)

GO

SET IDENTITY_INSERT [dbo].[Product] ON
INSERT [dbo].[Product] ([ProductId], [ProductName]) VALUES (1, N'Product_A1')
INSERT [dbo].[Product] ([ProductId], [ProductName]) VALUES (2, N'Product_A2')
INSERT [dbo].[Product] ([ProductId], [ProductName]) VALUES (3, N'Product_B1')
INSERT [dbo].[Product] ([ProductId], [ProductName]) VALUES (4, N'Product_B2')
INSERT [dbo].[Product] ([ProductId], [ProductName]) VALUES (5, N'Product_B3')
SET IDENTITY_INSERT [dbo].[Product] OFF

GO

Пример данных:

[Product Table]

ProductId ProductName

1   Product_A1
2   Product_A2
3   Product_B1
4   Product_B2
5   Product_B3


[ProductProperty  Table]

Id ProductId InfoKey InfoValue

1   1   k1  v1
3   2   k1  v1
4   3   k1  v2
6   5   k1  v1
7   2   k2  v1
8   1   k2  v1
9   5   k2  v2
10  2   k3  v2
11  3   k3  v2
12  5   k3  v1

Я хочу получить productIds, где ProductProperty продукта k1 = v1 и k2 = v1, примерно так:

(InfoKey='k1' AND InfoValue='v1') and (InfoKey='k2' AND InfoValue='v1')

Результат должен быть:

ProductId
1
2

Как я могу сделать это в Sql или LinqToSql?

Ответы [ 2 ]

1 голос
/ 27 июня 2011

Если число проверяемых условий свойства является статическим (в данном случае два), тогда вы можете выполнить этот запрос, как показано ниже.Если нет, пожалуйста, отправьте ответ и дайте нам знать, если вам нужно, чтобы он был более динамичным (для поддержки трех, четырех и т. Д. Условий)

select  ProductId
from    dbo.productproperty
where   (InfoKey='k1' AND InfoValue='v1') or 
        (InfoKey='k2' AND InfoValue='v1')
group 
by      ProductId 
having  count(*) = 2;

РЕДАКТИРОВАТЬ: для счетчика динамических условий

;with c_stage (k, v)
as  (   select 'k1', 'v1' union all
        select 'k2', 'v1'
    )
select  ProductId
from    dbo.productproperty pp
join    c_stage t on 
        pp.InfoKey = t.k and 
        pp.InfoValue = t.v
group 
by      ProductId 
having  count(*) = (select count(*) from c_stage);
1 голос
/ 27 июня 2011

Запрос будет выглядеть следующим образом:

var q = 
    from product in db.Product
    where
        db.ProductProperty.Any(arg => arg.ProductId = product.Id && arg.InfoKey = "k1" && arg.InfoValue = "v1") &&
        db.ProductProperty.Any(arg => arg.ProductId = product.Id && arg.InfoKey = "k2" && arg.InfoValue = "v1")
    select product.Id;

С этим конкретным условием его можно упростить следующим образом:

var q =
    from product in db.Product
    let properties = db.ProductProperty.Where(arg => arg.ProductId = product.Id && arg.InfoValue = "v1")
    where
        properties.Any(arg => arg.InfoKey = "k1") &&
        properties.Any(arg => arg.InfoKey = "k2")
    select product.Id;

Если условия динамические:

var q =
    from product in db.Product
    select
        new
        {
            Product = product,
            Properties = db.ProductProperty.Where(arg => arg.ProductId = product.Id)
        };

if (something1)
    q = q.Where(arg => arg.InfoKey = "k1" && arg.InfoValue = "v1");
if (something2)
    q = q.Where(arg => arg.InfoKey = "k2" && arg.InfoValue = "v1");

var result = q.Select(arg => new { arg.Product.Id, arg.Product.Name }).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...