C++ SQL根据一个表中的行而不是另一个表中的行更新并联接三个表
我需要做一个有点复杂的sql查询,我有点卡住了。如果这改变了什么,我将使用SQLite 我有以下表格结构:C++ SQL根据一个表中的行而不是另一个表中的行更新并联接三个表,c++,sql,sqlite,join,C++,Sql,Sqlite,Join,我需要做一个有点复杂的sql查询,我有点卡住了。如果这改变了什么,我将使用SQLite 我有以下表格结构: Table G --------- G_id (primary key) | Other cols ... ==================================== 21 22 23 24 25 26 27 (no g_to_s_map) 28
Table G
---------
G_id (primary key) | Other cols ...
====================================
21
22
23
24
25
26
27 (no g_to_s_map)
28
然后我还有两个映射表:
Table G_to_S_Map (1:1 mapping, unique values of both g_id and s_id)
----------
G_id (foreign key ref g)| S_id (foreign key ref s)
===================================================
21 1
22 2
23 3
24 4
25 5
26 6
28 9
仅给定T\u id和G\u id,我需要能够使用第一个S\u id来更新G\u-to\u-S\u映射,第一个S\u id对应于指定的T\u-id(在S\u-to\u-T\u映射中)
我想到的第一件事就是得到任何与S\u-to\u地图中的T\u-id相对应的S\u-id:
SELECT S_id FROM S_to_T_Map where T_id = GIVEN_T_ID;
然后我大概会用G_-to_-S_映射将这些值连接起来,可能使用左/右连接,然后查找第一个不存在于其中一侧的值?然后,我需要根据S\u id和给定的\u id值或其他内容,插入到G\u-to\u-S\u映射中
有什么关于如何进行的建议吗?谢谢
编辑:添加了一些虚拟数据:嗯,下面的操作似乎很好,尽管我还没有将“插入”与之结合起来
Select s.S_ID from S as s
inner join(
Select st.S_ID from s_to_t_map as st
where st.T_ID=???? AND not exists
(Select * from g_to_s_Map as gs where gs.S_ID = st.S_ID)
) rslt on s.S_ID=rslt.S_ID ORDER BY s.s_Num ASC limit 1;
我认为这应该是可行的:
INSERT INTO G_To_S_Map (G_id, S_id)
(SELECT :inputGId, a.S_id
FROM S_To_T_Map as a
LEFT JOIN G_To_S_Map as b
ON b.S_id = a.S_id
AND b.G_id = :inputGId
WHERE a.T_id = :inputTId
AND b.G_id IS NULL
ORDER BY a.S_id
LIMIT 1);
编辑: 如果要按其他表格进行排序,请使用以下版本:
INSERT INTO G_To_S_Map (G_id, S_id)
(SELECT :inputGId, a.S_id
FROM S_To_T_Map as a
JOIN S as b
ON b.S_id = a.S_id
LEFT JOIN G_To_S_Map as c
ON c.S_id = a.S_id
AND c.G_id = :inputGId
WHERE a.T_id = :inputTId
AND c.G_id IS NULL
ORDER BY b.S_num
LIMIT 1);
(顺便说一句,我真的希望您的表不是这样命名的,因为这是一件可怕的事情。尤其应该避免使用Map
)
编辑: 下面是一些示例测试数据。我错过什么了吗?我对关系的概念化有误吗
S_To_T_Map
================
S_ID T_ID
1 1
2 1
3 1
1 2
1 3
3 3
G_To_S_Map
==================
G_ID S_ID
1 1
3 1
2 1
3 2
2 3
3 3
结果关联数据:(用于生成交叉连接测试数据的CTE)
编辑: 啊,好吧,现在我明白问题了。我的问题是,我假设
S
和G
之间存在某种多个关系。由于情况并非如此,请使用本修订声明:
INSERT INTO G_To_S_Map (G_id, S_id)
(SELECT :inputGId, a.S_id
FROM S_To_T_Map as a
JOIN S as b
ON b.S_id = a.S_id
LEFT JOIN G_To_S_Map as c
ON c.S_id = a.S_id
OR c.G_id = :inputGId
WHERE a.T_id = :inputTId
AND c.G_id IS NULL
ORDER BY b.S_num
LIMIT 1);
具体地说,对于包含G\u Id
的行,行检查G\u-S\u映射
需要从使用和切换到或——之前未指定的关键要求是G\u-Id
和S\u-Id
在G\u-S\u映射中都是唯一的
如果提供的G_Id
之前已映射,或者映射到给定T_Id
的所有S_Id
S已映射,则此语句不会插入一行。如果没有ORDER BY
,您将得到一个“随机”行。并停止使用“更新”,这在SQL中有非常特殊的含义。标记到表S
是没有意义的,因为我假设您有必要的fk引用。是的,我的语法中有一个ORDER BY,只是出于此目的而将其删除。是的,我的意思是“插入”而不是“更新”,忘记了条目还不存在。很有趣。谢谢为什么在S_to_T_映射的选择中有一个:inputGId?我想你的比我的多个选择更有效。但是,如果我想按表“s”中名为“s_Num”的字段排序,该怎么办?我使用:
作为主机变量(我不知道您的语法是什么样的)。我在SELECT
部分中使用它的原因是我希望G_To_S_Map
的结果引用为空-不会有来自表的引用要使用。答案经过编辑,包括对表S
Ah的参考,谢谢!是的,这些只是经过净化的变量名,否则我会疯狂地使用它们:我只是想知道,这句话是什么:“ON s.id=a.s_id”?不知道s.id应该是什么。也许是b.s_id。还有,“cb.G_id=:inputGId”是指“c.G_id”吗?这些变量名很残酷,我的错;)不幸的是,它似乎不起作用。当我使用上面的更改运行“g_到s_映射”时,我得到了一个已经在其中的值。它只是给我一个s_num最小的值,不管它是否在表中。
INSERT INTO G_To_S_Map (G_id, S_id)
(SELECT :inputGId, a.S_id
FROM S_To_T_Map as a
JOIN S as b
ON b.S_id = a.S_id
LEFT JOIN G_To_S_Map as c
ON c.S_id = a.S_id
AND c.G_id = :inputGId
WHERE a.T_id = :inputTId
AND c.G_id IS NULL
ORDER BY b.S_num
LIMIT 1);
S_To_T_Map
================
S_ID T_ID
1 1
2 1
3 1
1 2
1 3
3 3
G_To_S_Map
==================
G_ID S_ID
1 1
3 1
2 1
3 2
2 3
3 3
Results:
=============================
G_TEST T_TEST S_ID
1 1 3
2 1 2
1 3 3
INSERT INTO G_To_S_Map (G_id, S_id)
(SELECT :inputGId, a.S_id
FROM S_To_T_Map as a
JOIN S as b
ON b.S_id = a.S_id
LEFT JOIN G_To_S_Map as c
ON c.S_id = a.S_id
OR c.G_id = :inputGId
WHERE a.T_id = :inputTId
AND c.G_id IS NULL
ORDER BY b.S_num
LIMIT 1);