我需要做一些复杂的SQL查询,而且我有点卡住了。我正在使用SQLite,如果它改变了什么。
我有以下表结构:
Table G
---------
G_id (primary key) | Other cols ...
====================================
21
22
23
24
25
26
27 (no g_to_s_map)
28
Table S
---------
S_id (primary key) | S_num | Other cols.....
====================================
1 1101
2 1102
3 1103
4 1104
5 1105
6 1106
7 1107 (no g_to_s_map, no s_to_t_map)
8 1108 (no g_to_s_map, there IS an s_to_t_map)
9 1109 (there is an g_to_s_map, but no s_to_t map)
Table T
---------
T_id (primary key) | Other cols...
==================================
1
2
然后我还有两个映射表:
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
Table S_to_T_Map (many:1 mapping, many unique s_id to a t_id)
----------
S_id (foreign key ref s) | T_id (foreign key ref s)
===================================================
1 1
2 1
3 1
4 2
5 2
6 2
8 2
只有 T_id 和 G_id ,我需要能够使用第一个 S_id 更新 G_to_S_Map strong>对应于指定的 T_id (在 S_to_T_Map 中),不在 G_to_S_Map
中我想到的第一件事就是在 S_to_T_Map 中获得与 T_id 相对应的 S_id :
SELECT S_id FROM S_to_T_Map where T_id = GIVEN_T_ID;
然后假设我会以某种方式使用左/右连接以 G_to_S_Map 加入这些值,然后查找其中一侧不存在的第一个值?然后我需要根据 S_id 和 GIVEN_G_ID 值等插入 G_to_S_Map 。
有关如何解决这个问题的任何建议?谢谢!
编辑:添加了一些虚拟数据:
答案 0 :(得分:2)
我相信这应该有效:
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用于生成交叉连接测试数据)
Results:
=============================
G_TEST T_TEST S_ID
1 1 3
2 1 2
1 3 3
<小时/> 编辑:
啊,好吧,现在我遇到了问题。我的问题是我假设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_To_S_Map
的行检查G_Id
的行从使用AND
切换为OR
- 关键要求之前未指定的是G_Id
和S_Id
在G_To_S_Map
中唯一的事实。
如果先前已映射提供的G_Id
,或者映射到给定S_Id
的所有T_Id
已映射,则此语句不会插入行。
答案 1 :(得分:0)
嗯,以下似乎很好用,虽然我还没有把“插入”与它结合起来。
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;