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;