Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在SQLServer中对EAV表进行多选筛选_Sql Server_Where Clause_Entity Attribute Value - Fatal编程技术网

Sql server 如何在SQLServer中对EAV表进行多选筛选

Sql server 如何在SQLServer中对EAV表进行多选筛选,sql-server,where-clause,entity-attribute-value,Sql Server,Where Clause,Entity Attribute Value,我有一个带有属性的EAV表,并且希望根据传递到存储过程中的变量对项目进行混合选择 样本表: | group_id | item_id | key | value | +----------+---------+--------+-------+ | 1 | AA | length | 10 | | 1 | AA | width | 10 | | 1 | AA | color | white | | 1

我有一个带有属性的EAV表,并且希望根据传递到存储过程中的变量对项目进行混合选择

样本表:

| group_id | item_id | key    | value |
+----------+---------+--------+-------+
| 1        | AA      | length | 10    |
| 1        | AA      | width  | 10    | 
| 1        | AA      | color  | white |
| 1        | AA      | brand  | beta  |
| 1        | BB      | length | 25    |
| 1        | BB      | brand  | alpha |
| 2        | CC      | brand  | alpha |
示例查询:

declare @attributes nvarchar(max) = 'brand name, length'
declare @attributeValues nvarchar(max) = 'alpha, beta, 25'
declare @id int = 1

select *
into #allProductsFromGroup
from items
where group_id = @id

select item_id
from #allProductsFromGroup #all
where [key] in (select value from string_split(@attributes, ',')) 
  and [value] in (select value from string_split(@attributeValues, ','))
预期产出:

| item_id |
+---------+
| BB      |
我可以为每个
硬编码
以及
语句,但是有很多,我正在寻找一个更具可扩展性的解决方案

传入并解析JSON会很好,比如:

[
  { "brand": "aplha" },
  { "brand": "beta" },
  { "length": 25 }
]

如何编写第二个
select
来动态返回
allProductsFromGroup
的子集,该子集动态地包含来自同一组(多选品牌或多选长度)的多个结果,但从其他组(颜色、长度等)中排除?

目标查询可能如下所示:

with q as
(
    select item_id,
       max( case when [key] = 'brand' then [value] end ) brand,
       max( case when [key] = 'length' then cast( [value] as int ) end ) length,
    from #allProductsFromGroup 
    group by Item_id
)
select item_id
from q
where brand in ('alpha','beta') and length=25
您只需从传入的数据构建它(糟糕)。要生成的更简单的查询表单可能如下

select item_id
from #allProductsFromGroup 
where [key] = 'brand' and [value] in ('alpha','beta')
intersect 
select item_id
from #allProductsFromGroup 
where [key] = 'length' and [value] = 25

标准映射到
相交
,将
标准映射到
联合
。它也可能更便宜,因为每个查询都可以在(key,value)上查找索引。

这可能是一个迟来的答案,但是如果您可以将条件作为JSON传递,那么下一种方法也是一种可能的解决方案。JSON的格式必须与答案中的格式相同,并且可以使用两个以上的条件:

表:

CREATE TABLE Data (
   group_id int,
   item_id varchar(2),
   [key] varchar(100),
   [value] varchar(100)
)
INSERT INTO Data (group_id, item_id, [key], [value])
VALUES
   (1, 'AA', 'length', '10'),
   (1, 'AA', 'width',  '10'),
   (1, 'AA', 'color',  'white'),
   (1, 'AA', 'brand',  'beta'),
   (1, 'BB', 'length', '25'),
   (1, 'BB', 'brand',  'alpha'),
   (2, 'CC', 'brand',  'alpha')
作为JSON的条件:

DECLARE @conditions varchar(max) = N'
[
   {"key": "brand", "values": ["alpha", "beta"]},
   {"key": "length", "values": ["25"]}
]
'
声明:

SELECT d.item_id
FROM Data d
JOIN (
   SELECT j1.[key], j2.[value]
   FROM OPENJSON(@conditions) WITH (
      [key] varchar(100) '$.key',
      [values] nvarchar(max) '$.values' AS JSON
   ) j1
   CROSS APPLY OPENJSON(j1.[values]) j2
) o ON d.[key] = o.[key] AND d.[value] = o.[value]
GROUP BY d.item_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM OPENJSON(@conditions))
结果:

item_id
BB

只是想说明一下-您希望
所在的行与
bramd
aplha
,或
name
beta
相同,或者
length
25
?其中
key=brand&value=alpha或beta
key=length和value=25
因此对于一个结构合理的表来说,等同于
Where brand in('alpha','beta')、length=25
?好吧,EAV是一种糟糕的做法,所以那艘船已经开航了。@Matthew如果将标准作为JSON传递是一种选择,那么可能是像
{“brand”:[“aplha”,“beta”],“length”:[“25”]}
这样的JSON结构看起来更好。谢谢!我需要一些时间来思考这个问题。。。我希望使用类似于
json\u query
的东西来为where子句引入数据。我以前没用过intersect。。。感谢您周到的回复!