我可以编写典型的“SELECT A,C FROM B WHERE B.id = 10”查询,但是其他方面很少使用SQL,我需要对此查询做的事情远远超出我的SQL经验这一点。
我有一个带有主键Tid的表T和一个SQLite中的特殊列S.我想创建另一个表,它是由Tid值组成的单个列。我需要我的新表为每个可能的S值提供1000个随机的Tid值。
因此,如果我要将S分组为S,那么我的新表将代表每组中的1000个随机原则键。
什么SQLlite查询会创建这样的表?
注意:表T很大,因此性能更好的查询更好。
答案 0 :(得分:2)
更新:我提出了一个比第一个更简单的解决方案。
首先,我们创建一个表来将结果放入:
CREATE TABLE result(tid integer primary key, s);
在此过程结束时,result
将包含原始表格s
中每个唯一t
值的每组中的1000行。
基本的想法是创造一个魔术"包含一列s
的特殊视图,其具有以下属性:每次我们尝试向其中插入s
的任何值时,相反,来自t
的1000个具有相同值的随机行系统会选择s
并将其插入result
。我们可以通过触发器来做到这一点:
CREATE TEMP VIEW result_view AS SELECT null AS s WHERE 0;
CREATE TEMP TRIGGER result_ins_trigger
INSTEAD OF INSERT ON result_view FOR EACH ROW
BEGIN
INSERT INTO result(tid, s)
SELECT * FROM t WHERE t.s=NEW.s ORDER BY random() LIMIT 1000;
END;
现在我们有了这个视图,我们尝试将s
的所有不同值插入其中,触发器将完成其余的操作:
INSERT INTO result_view SELECT DISTINCT s FROM t;
请注意,如果您在t(s)
上有索引,则流程会明显加快,因此可能需要先创建(然后在不需要时删除它)。
基本上,上述解决方案是使用触发器的LATERAL
子查询的穷人实现。
原始回答:这是一个使用临时触发器的解决方案。首先,我们创建一个表来将结果放入:
CREATE TABLE result(tid integer primary key, s, num NOT NULL);
在此过程结束时,result
将包含原始表s
中每个唯一t
值的每组中的1000行。该表还有一个名为num
的辅助列。然后我们执行以下操作:
CREATE INDEX result_s_idx ON result(s, num);
CREATE TEMP VIEW result_view AS SELECT null AS TID, null AS s, NULL AS num WHERE 0;
CREATE TEMP TRIGGER result_ins_trigger
INSTEAD OF INSERT ON result_view FOR EACH ROW
BEGIN
INSERT INTO result(tid, s, num)
SELECT NEW.tid, NEW.s,
COALESCE((SELECT max(num) FROM result WHERE s=NEW.s),0)+1 AS num
WHERE num<=1000;
END;
INSERT INTO result_view(tid, s, num)
SELECT tid,s,null FROM t ORDER BY random();
DROP INDEX result_s_idx;
我的想法是尝试以随机顺序将t
中的所有内容插入到result
中,为每一行分配一个数字(存储在num
列中),表示什么是该组中该元素的位置(以随机顺序)。所以例如如果num
为11,则表示该行是该组的第11行。另外,如果数字大于1000,那么我们丢弃该行,因为每组只需要1000行。为了阻止先前的逻辑,我们使用触发器,以便对于我们尝试插入的每一行,它运行子查询来计算num
的正确值,并在num
更大时丢弃该行由于sqlite不允许在常规表上使用INSTEAD OF
触发器,因此我们在虚拟临时视图上创建该触发器。最后,我们将t
中的所有行插入到虚拟视图中(以便触发器以随机顺序启动)。
基本上,上述解决方案是使用触发器的row_number
窗口函数的穷人实现。
最后一个问题是num
的辅助列result
。如果您对此感到困扰,可以通过创建没有它的新表并从result
复制所有数据来删除它。