【问题标题】:Join and select only if left side rows contain all the declared rows仅当左侧行包含所有声明的行时才加入和选择
【发布时间】:2022-01-19 03:21:40
【问题描述】:

首先,对于含糊的标题,我深表歉意。我有两个表:DevicesDeviceProperties

[ Devices ]    
[ id ]
[ AA ]
[ BB ]
[ CC ]

[ DeviceProperties ]
[ id ][ propertyType ][  propertyKey ][ valueType ][      value ]
[ AA ][      desired ][ scanInterval ][    Number ][        100 ]
[ AA ][          tag ][        floor ][    Number ][        200 ]
[ AA ][      desired ][         name ][    String ][  AA_Device ]
[ BB ][      desired ][ scanInterval ][    Number ][        100 ]
[ BB ][          tag ][        floor ][    Number ][        200 ]
[ CC ][          tag ][        floor ][    Number ][        200 ]

我想选择所有具有特定设备属性的设备:

-- Select devices that have these DeviceProperties
[      desired ][ scanInterval ][    Number ][        100 ]
[          tag ][        floor ][    Number ][        200 ]

我声明了 N 个变量。每组 4 个声明的变量代表 DeviceProperties 表中不同的设备属性/行。

DECLARE @propertyType_1 nvarchar(max) = 'desired';
DECLARE @propertyKey_1 nvarchar(max) = 'scanInterval'
DECLARE @valueType_1 nvarchar(max) = 'Number'
DECLARE @value_1 nvarchar(max) = '100'
-- [      desired ][ scanInterval ][    Number ][        100 ]

DECLARE @propertyType_n nvarchar(max) = 'tag';
DECLARE @propertyKey_n nvarchar(max) = 'floor'
DECLARE @valueType_n nvarchar(max) = 'Number'
DECLARE @value_n nvarchar(max) = '200'
-- [          tag ][        floor ][    Number ][        200 ]

假设我有一个有效的查询,它只会返回以下设备:

[ Devices ]    
[ id ]
[ AA ]
[ BB ]

不会返回设备 CC,因为它只有 DeviceProperty

[          tag ][        floor ][    Number ][        200 ]

但不是

[      desired ][ scanInterval ][    Number ][        100 ]

我真的很困惑我应该写什么样的查询。一个简单的 WHERE 查询在这里不起作用。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    在临时表中插入所需的匹配条件

    insert into #temp (propertyType, propertyKey, valueType, value)
    values ('desired', 'scanInterval', 'Number', 100),
           ('tag',     'floor',        'Number', 200);
    

    将其加入您的表,GROUP BYid,匹配行数必须为 N。对于给出的示例,N = 2

    SELECT d.id
    FROM   Devices d
           INNER JOIN DeviceProperties p ON  d.id = p.id
           INNER JOIN #temp t            ON  p.propertyType = t.propertyType
                                         AND p.propertyKey  = t.propertyKey
                                         AND p.valueType    = t.valueType
                                         AND p.value        = t.value
    GROUP BY d.id
    HAVING COUNT(*) = 2
    

    【讨论】:

    • 感谢您的回答,非常感谢。我根据您的回答用我自己的查询添加了另一个答案。也许它也有效。
    【解决方案2】:

    松鼠给了我一个主意。不确定这是否是一种理想的方法,但我也可以这样做:

    select
        d.deviceId
    from
        Devices as d
    join
        DeviceProperties as p
    on
        d.deviceId = p.deviceId
    where
        p.propertyType in (@pt_0, @pt_1) and 
        p.propertyKey in (@pk_0, @pk_1) and 
        p.value in (@pv_0, @pv_1)
    group by
        d.deviceId
    having
        COUNT(*) = 2
    

    【讨论】:

    • 使用临时表而不是这里的原因是您注意到您有 N 个变量。如果您知道变量集的数量,您的答案效果很好,如果您不知道从运行到运行的变量集的数量,您将需要一个临时表或类似的解决方案。
    • 变量列表/变量集是已知的并由我提供。我用 N 来描述我可能有 1 组、4 组或任何其他数字组。
    • 这个查询的问题是如果你有像desired - floor - Number - 100这样的行,它也会出现在结果中。见demo
    猜你喜欢
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2020-10-18
    • 2017-04-29
    相关资源
    最近更新 更多