在我们的系统中,我们有1000多个表,每个表都有一个' date'包含DateTime对象的列。我想获得一个列表,其中包含所有表中存在的每个日期。我确信应该有一个简单的方法来做到这一点,但我对postgresql或sqlalchemy的知识非常有限。
在postgresql中,我可以在两个表上进行完全连接,但对于单个公共字段,似乎没有办法在模式中的每个表上进行连接。
然后我尝试用sqlalchemy在python中以编程方式解决这个问题。对于每个表格,我确实为“日期”创建了一个选择区别。列,然后将该选择列表设置为CompoundSelect对象的choices属性,并执行。正如人们可能从一个丑陋的暴力查询中得到的那样,它现在已经运行了一个小时左右,而且我不确定它是否在某个地方默默地打破并且永远不会返回。
有没有干净,更好的方法来做到这一点?
答案 0 :(得分:2)
您肯定希望在服务器上执行此操作,而不是在应用程序级别执行此操作,因为应用程序和服务器之间存在多次往返,并且可能会在中间结果中重复数据。
由于您需要处理1,000多个表,因此您应该使用系统目录并动态查询表。您需要一个有效的功能:
CREATE FUNCTION get_all_dates() RETURNS SETOF date AS $$
DECLARE
tbl name;
BEGIN
FOR tbl IN SELECT 'public.' || tablename FROM pg_tables WHERE schemaname = 'public' LOOP
RETURN QUERY EXECUTE 'SELECT DISTINCT date::date FROM ' || tbl;
END LOOP
END; $$ LANGUAGE plpgsql;
这将处理public
架构中的所有表格;根据需要改变。如果表是多个模式,则需要在存储表的位置插入附加逻辑,或者可以使模式名称成为函数的参数并多次调用函数并UNION
结果。
请注意,您可能会从多个表中获得重复的date
个。这些重复项可以在调用函数的语句中清除:
SELECT DISTINCT * FROM get_all_dates() ORDER BY 1;
该函数在内存中创建结果集,但如果1,000+表中行中不同日期的数量非常大,则结果将写入磁盘。如果您希望这种情况发生,那么最好在函数开头创建一个临时表并将日期插入该临时表中。
答案 1 :(得分:1)
结束恢复到之前使用SqlAlchemy运行查询的解决方案。这使我可以并行化并快速运行 little ,因为它确实是一个非常大的查询。
我对帮助此查询的数据集了解了一些事情 - 我只想要每个表中的不同日期,并且日期是我的集合中的PK。我最终使用this wiki page的方法。在查询中发送的代码如下所示:
WITH RECURSIVE t AS (
(SELECT date FROM schema.tablename ORDER BY date LIMIT 1)
UNION ALL SELECT (SELECT knowledge_date FROM schema.table WHERE date > t.date ORDER BY date LIMIT 1)
FROM t WHERE t.date IS NOT NULL)
SELECT date FROM t WHERE date IS NOT NULL;
我将该查询的结果拖到我所有日期的列表中(如果它们已经不在列表中),然后将其保存以供日后使用。它可能只需要在pgsql控制台中运行它就可以了,但是我在本地保存比在必须查询db中的临时表更容易。