SQLite交叉引用唯一组合

SQLite交叉引用唯一组合,sqlite,Sqlite,我已经用给定模式的数据填充了两个表: CREATE TABLE objects ( id BIGINT NOT NULL, latitude BIGINT NOT NULL, longitude BIGINT NOT NULL, PRIMARY KEY (id) ) CREATE TABLE tags ( id BIGINT NOT NULL, tag_key

我已经用给定模式的数据填充了两个表:

    CREATE TABLE objects
    (
        id BIGINT NOT NULL,
        latitude BIGINT NOT NULL,
        longitude BIGINT NOT NULL,
        PRIMARY KEY (id)
    )
    CREATE TABLE tags
    (
        id BIGINT NOT NULL,
        tag_key VARCHAR(100) NOT NULL,
        tag_value VARCHAR(500),
        PRIMARY KEY (id , tag_key)
    )
object.id和tags.id指的是同一个对象

我想用tag_key和tag_value的独特组合填充第三个表。例如:

    INSERT OR REPLACE INTO objects (id) VALUES (0);
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (0, 'a', 'x');
    INSERT OR REPLACE INTO objects (id) VALUES (1);
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (1, 'a', 'y');
    INSERT OR REPLACE INTO objects (id) VALUES (2);
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (2, 'a', 'x');
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (2, 'a', 'y');
    INSERT OR REPLACE INTO objects (id) VALUES (3);
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (3, 'a', 'x');
    INSERT OR REPLACE INTO objects (id) VALUES (4);
    INSERT OR REPLACE INTO tags (id, tag_key, tag_value) VALUES (4, 'a', 'y');
应导致3项

0: ([a,x]) 
1: ([a,y]) 
3: ([a,x][a,y])
目前我有:

    CREATE TABLE tags_combinations
    (
        id INTEGER PRIMARY KEY,
        tag_key VARCHAR(100) NOT NULL,
        tag_value VARCHAR(500)
    );
id不应该与对象的原始id相关,而应该是对唯一组合进行分组的内容

这是我到目前为止提出的问题:

    SELECT
        t1.tag_key, t1.tag_value
    FROM
        tags t1
    WHERE
        t1.id
    IN
        (
    /* select ids who's every tags entry is not under one id in tags_combinations */
            SELECT 
                t2.id 
            FROM
                tags t2
            WHERE
                t2.tag_key, t2.tag_value
            NOT IN
            (

            )
        );
带有注释的部分是我不确定的,我如何从标签中选择每个id,如果标签组合中的一个id下没有所有对应的标签键和标签值条目

为了准确地阐明我所追求的结果:从给定的示例数据中,它应该返回4行,其中包含:

row id tag_key tag_value    
 0   0   a         x
 1   1   a         y
 2   2   a         x
 3   2   a         y

要将多行合并为一个值,需要一个函数,如

需要ORDER BY以确保组内行的顺序一致:

SELECT DISTINCT group_concat(tag_key) AS tag_keys,
                group_concat(tag_value) AS tag_values
FROM (SELECT id,
             tag_key,
             tag_value
      FROM tags
      ORDER BY id,
               tag_key,
               tag_value)
GROUP BY id;
如问题所示,如果要使键和值交错,则需要执行更多的字符串串联:

SELECT DISTINCT group_concat(tag_key || ',' || tag_value, ';') AS keys_and_values
FROM (...

这在SQLite中并不容易。我们想要识别标记键/值对的组。所以我们可以按id分组,得到一个和group_concat相关联的对字符串。这将是在另一个DBMS中执行此操作的方法。然而,SQLite不能在组_concat中排序,因此我们可能会得到2:'a/x,a/y'和5:'a/y,a/x'。同一对的两个不同字符串

您最好的选择可能是编写一个程序并迭代地找到不同的对

在SQLite中,您可能希望尝试以下方法:

insert into tags_combinations (id, tag_key, tag_value)
  select id, tag_key, tag_value
  from tags
  where id in
  (
    select min(id)
    from
    (
      select id, group_concat(tag_key || '/' || tag_value) as tag_pairs
      from
      (
        select id, tag_key, tag_value
        from tags
        order by id, tag_key, tag_value
      ) ordered_data
      group by id
    ) aggregated_data
    group by tag_pairs
  );

在应用group_concat之前对数据进行排序很可能会使标记对有序,但无法保证!如果这是您只想做一次的事情,那么可能值得一试。

SQL是一种基于集合的语言。如果你用集合论的语言重新表述你的问题,你可以直接把它翻译成SQL:

您需要tags表的所有行,但重复对象中的行除外。 如果对象具有完全相同的键/值组合,则它们是重复的。但是,我们仍然希望返回其中一个对象,因此我们仅将重复定义为那些不存在其他ID较小的重复对象的对象。 两个对象A和B具有完全相同的键/值组合,如果 A中的所有键/值组合也存在于B中,并且 B中的所有键/值组合也存在于A中。 如果A中没有B中不存在的键/值组合,则A中的所有键/值组合也存在于B中注:双重否定。
表对象似乎完全多余。在填充标记和组合后,您是否要删除表标记?或者您会从标记中删除标记\键和标记\值,并用id \标记\组合替换它们吗?为了不在数据模型中引入冗余,您应该执行这两种操作中的任何一种。感谢@Thorsten Kettner,对象实际上有更多的信息,但在本例中我省略了它。理想情况下是的,我会用一个id替换标签表,该id引用标签组合中的相应条目。顺便说一下:到目前为止,标签组合中只有id作为主键。因此,不能为ID 2插入两条记录。您缺少一个额外的GROUP_NUMBER列或任何您想调用的存储分组ID的列。作为主键的ID将在插入时自动填充一些值。这也不是我想要的。从给定的示例数据中,它应该返回4行:0:[a,x]1:[a,y]2:[a,x]2:[a,y]好的,非常感谢您的建议。我将用宿主语言解决这个问题,这是一个相当琐碎的问题。我希望在SQLite中找到一个解决方案,尽可能保持它的可伸缩性。再次感谢!SQLite事实上,内部ORDER BY没有根据规则16进行优化。@CL:即使如此,GROUP_CONCAT也远不能保证以任何方式使用该顺序:连接元素的顺序是任意的。通过对临时表中的数据进行一些预筛选,然后应用您的查询,我达到了我的目标。非常感谢,特别是解释。
SELECT id, tag_key, tag_value
FROM tags
WHERE NOT EXISTS (SELECT 1
                  FROM tags AS dup
                  WHERE dup.id < tags.id
                    AND NOT EXISTS (SELECT 1
                                    FROM tags AS A
                                    WHERE A.id = tags.id
                                      AND NOT EXISTS (SELECT 1
                                                      FROM tags AS B
                                                      WHERE B.id = dup.id
                                                        AND B.tag_key   = A.tag_key
                                                        AND B.tag_value = A.tag_value)
                                   )
                    AND NOT EXISTS (SELECT 1
                                    FROM tags AS B
                                    WHERE B.id = dup.id
                                      AND NOT EXISTS (SELECT 1
                                                      FROM tags AS A
                                                      WHERE A.id = tags.id
                                                        AND A.tag_key   = B.tag_key
                                                        AND A.tag_value = B.tag_value)
                                   )
                 )
ORDER BY id, tag_key;