根据多个条件筛选表,其中项目属性作为单独的行输入

62lalag4  于 2022-10-22  发布在  其他
关注(0)|答案(6)|浏览(120)

我继承了SQL Server表设计,如下所述。该表称为Info
我需要理解返回以下两个示例的正确结果所需的SQL语句。

Id  | ItemId | FieldName | Value
 1  | 302    | Colour    | Red
 2  | 303    | Length    | 100
 3  | 304    | Length    | 25
 4  | 305    | Colour    | Blue
 5  | 306    | Colour    | Blue
 6  | 306    | Length    | 100
 7  | 307    | Colour    | Blue
 8  | 307    | Length    | 35
 9  | 308    | Colour    | Red
 10 | 308    | Length    | 100
 11 | 309    | Colour    | Red
 12 | 309    | Length    | 45
 13 | 309    | Shape     | Square
 14 | 310    | Shape     | Round

示例1:我需要从“信息”表中找出哪些项目(ItemId)的颜色为“红色”,长度为“100”-应该是,ItemId 308
我有限的SQL知识使我走上了

SELECT ItemId 
FROM Info 
WHERE (FieldName = 'Colour') 
  AND (Value = 'Red')

但这返回项302和308

SELECT ItemId 
FROM Info 
WHERE (FieldName = 'Length') 
  AND (Value = '100')

返回303和308,此时正确的输出应该是ItemId 308
我的场景可能还需要扩展此查询,以包含两个以上的字段,如以下示例所示:
示例2:我需要找出哪些项目的颜色为“红色”,长度为“45”,并且是“方形”-应该只有ItemId 309
如有任何建议,我们将不胜感激。

lztngnrs

lztngnrs1#

我想这会满足你的要求。我使用LEFT OUTER JOIN s连接您正在搜索的每个参数。然后在顶部使用SELECT DISTINCT获取ItemId。

DECLARE @SearchColor nvarchar(50) = 'Red';
DECLARE @SearchLength nvarchar(50) = '100';

SELECT DISTINCT i.ItemId
FROM Info as i
    LEFT OUTER JOIN Info as iColor
        ON iColor.ItemId = i.ItemId 
        AND iColor.FieldName = 'Colour'
        AND iColor.Value = @SearchColor
    LEFT OUTER JOIN Info as iLength
        ON iLength.ItemId = i.ItemId 
        AND iLength.FieldName = 'Length'
        AND iLength.Value = @SearchLength
WHERE iColor.Id IS NOT NULL
    AND iLength.Id IS NOT NULL
;
cyvaqqii

cyvaqqii2#

这是一个经典的“剩余”问题

有很多解决方案,但如果你想使其灵活并能够处理不同数量的属性,那么你需要规范化你的输入。您可以使用表变量、临时表或TVP进行此操作。
一个常见且性能良好的解决方案是连接输入,将其分组并检查是否有足够的行

DECLARE @input TABLE (FieldName nvarchar(100), Value nvarchar(100), PRIMARY KEY (FieldName, Value));
INSERT @input VALUES
('Colour', 'Red'),
('Length', '100');

SELECT i.ItemId 
FROM Info i
JOIN @input inp
  ON inp.FieldName = i.FieldName
 AND inp.Value = i.Value
GROUP BY
  i.ItemId
HAVING COUNT(*) = (SELECT COUNT(*) FROM @input);
fdx2calv

fdx2calv3#

这里有一种方法可以在一个查询中获得两个结果并保留所有信息。

select   Id
        ,ItemId 
        ,FieldName  
        ,Value
from     (
          select   *
                  ,count(case when value = 'Red' then 1 when try_convert(int, value) = 100  then 1 end) over(partition by ItemId)                            as mrk 
                  ,count(case when value = 'Red' then 1 when try_convert(int, value) = 45 then 1 when value = 'Square' then 1 end) over(partition by ItemId) as mrk2 
          from     info
         ) info
where    mrk  = 2 
   or    mrk2 = 3
IdItemIdFieldName
9308颜色红色
10308长度100
11309颜色红色
12309长度45
13309形状正方形

Fiddle

slsn1g29

slsn1g294#

第一个例子:

select    ItemId
from     (
          select   ItemId
                  ,case when value = 'Red' then 1 end                   as mrk
                  ,case when try_convert(int, value) = 100  then 1 end  as mrk2
          from     info
         ) info
group by  ItemId
having    max(mrk)  = 1
   and    max(mrk2) = 1
项目ID
308

第二个例子:

select    ItemId
from     (
          select   ItemId
                  ,case when value = 'Red' then 1 end                  as mrk
                  ,case when try_convert(int, value) = 45  then 1 end  as mrk2
                  ,case when value = 'Square' then 1 end               as mrk3
          from     info
         ) info
group by  ItemId
having    max(mrk)  = 1
   and    max(mrk2) = 1
   and    max(mrk3) = 1
项目ID
309

Fiddle

oiopk7p5

oiopk7p55#

我们可以旋转并简单地检索信息。

select *
from
(
select ItemId, FieldName, Value
from   info
) info
pivot(max(Value) for FieldName in(Colour, Length, Shape)) p
where Colour = 'red' and Length = '100'
   or Colour = 'red' and Length = '45' and shape = 'square'
ItemId颜色长度形状
308红色100
309红色45方形

Fiddle

wfypjpf4

wfypjpf46#

试试这个:

SELECT ItemId 
FROM Info 
WHERE (FieldName = 'Colour' AND Value = 'Red')
AND (FieldName = 'Length' AND Value = 100)

相关问题