在关系数据库中设计键值对的最佳方法?

Dum*_*per 4 sql-server

我有一个表,其中包含任何对象可以具有的所有属性的列表:

attr_id attr_name attr_data_type
------ ----- --------------

我有一个表[object_key],其中每个表object_key_id都有一个唯一的列表,即一组 attr_id,attr_value 对。

object_key_id attr_id attr_value
--------- ------- ----------
1 1 '值 1'
1 2 '值 2'
2 1 '值 3'
2 2 'value4'
3 1 '值 1'
3 2 '值 2'
3 3 'value3'

在这种情况下,获得object_key_id给定attr_id,attr_value对的最佳方法是什么。

Ex: Input: [{1, 'value1'}, {2, 'value2'}] Output: 1

建立唯一索引的最佳方法是什么,即object_key_id对一组attr_id,attr_value对具有唯一性?

ype*_*eᵀᴹ 5

你想要的是(确切的)Relational Division

另见这篇文章:我们所持的分裂:关系分裂的 SQL

有几种方法可以让这样的查询解决这个问题。您可以将输入数据加载到(临时)表或使用这样的 CTE:

WITH input_data (attr_id, attr_value) AS
  ( SELECT *
    FROM 
      ( VALUES                              -- the input data. 
          (1, 'value1'), 
          (2, 'value2')
      ) AS i (attr_id, attr_value)
  ),
t AS                                        -- all the object_key_id values.
  ( SELECT DISTINCT object_key_id           -- if you have a separate table with those
    FROM tableX                             -- you can use it, instead. 
  )
SELECT object_key_id
FROM t
WHERE NOT EXISTS                            -- this subquery ensures
      ( SELECT attr_id, attr_value          -- that all input attribute/value pairs
        FROM input_data                     -- appear for an object_key
      EXCEPT
        SELECT attr_id, attr_value
        FROM tableX AS tt
        WHERE tt.object_key_id = t.object_key_id 
      ) 
  AND NOT EXISTS                            -- and this subquery does the reverse
       ( SELECT attr_id, attr_value         -- i.e. the exact part of the division
        FROM tableX AS tt
        WHERE tt.object_key_id = t.object_key_id 
      EXCEPT
        SELECT attr_id, attr_value
        FROM input_data
      ) ;
Run Code Online (Sandbox Code Playgroud)

SQL-Fiddle测试

StackOverflow 上的这个问题:How to filter SQL results in a has-many-through Relations有更多的方法可以解决它和 Postgres 的基准测试,但它不是针对确切的变化,仅针对"Division with Remainder"。查询将是相似的,但必须为确切的变化添加额外的检查/条件。