Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 循环内的SELECT语句_Sql_Postgresql - Fatal编程技术网

Sql 循环内的SELECT语句

Sql 循环内的SELECT语句,sql,postgresql,Sql,Postgresql,我们的应用程序使用Rails公寓gem,因此每个微站点都有自己的模式。因此,我们有50个模式,每个模式都有自己的用户表 使用SQL(Postgres),如何从所有50个模式中选择用户,而不必遍历每个模式 DO $$ DECLARE table_name text; BEGIN FOR schema_name IN SELECT schema FROM tenants LOOP EXECUTE 'SELECT * FROM ' || schema_name || '.users';

我们的应用程序使用Rails公寓gem,因此每个微站点都有自己的模式。因此,我们有50个模式,每个模式都有自己的用户表

使用SQL(Postgres),如何从所有50个模式中选择用户,而不必遍历每个模式

    DO $$
DECLARE
table_name text;
BEGIN
  FOR schema_name IN SELECT schema FROM tenants LOOP
EXECUTE 'SELECT * FROM ' ||  schema_name || '.users';
  END LOOP;
END;
$$;
结果

subdomain1, 'john smith'
subdomain1, 'mary smith'
subdomain2, 'charles geiger'
subdomain2, 'ann geiger'
subdomain3, 'allison reidy'
您可能需要运算符,特别是
UNION ALL

基本形式是:

SELECT a,b,c
  FROM schema1.table
UNION ALL
SELECT a,b,c
  FROM schema2.table
UNION ALL
SELECT ...
  ...
基本上,您可以将
UNION ALL
放在两个不同的
SELECT
语句之间,查询将在单个结果集中返回两个
SELECT
的结果

请注意,只有当两个
SELECT
查询返回相同的数据类型集时,这才有效。所以

SELECT an_int, another_int, a_text
  ...
UNION ALL
SELECT a_text, another_text, a_timestamp
  ...
将抛出一个错误

由于可以将它放在
SELECT
语句之间,因此可以将大量
SELECT
语句连成一行。是的,即使是97个,如果你需要的话

因为它可能很麻烦,人们常常会创建一个
UNION-ALL
查询的视图,然后反对它。在您的情况下,必须为每个新模式更新该视图,因此它可能不可行,但它是一个选项

哦,差点忘了。
ALL
部分的意思只是“返回每个查询的所有结果”。如果只使用
UNION
而不使用
ALL
,数据库将经历重复数据消除过程。例如,如果在两个不同的模式中有相同的
用户
,那么它只会返回其中一个模式
UNION ALL
将同时返回两者

最后,如果您确实创建了一个视图,那么包含源代码,这一点可以让事情变得更简单。差不多

CREATE VIEW blah AS
  SELECT 'schema1', a,b,c
    FROM schema1.table
  UNION ALL
  SELECT 'schema2', a,b,c
    FROM schema2.table
  UNION ALL
  ...

希望有帮助

这是生成要查找的查询的方法:

WITH relevant_tables AS (
  SELECT CONCAT(nspname, '.', relname) as table_name,
                 CONCAT('SELECT * FROM ', nspname, '.', relname) as table_query
      FROM pg_class c
      LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
      WHERE relkind = 'r'
      AND relname = 'users'
)
SELECT string_agg(table_query, ' UNION ALL ') as final_query FROM relevant_tables
然后可以使用
DO
块执行它

根据注释进行编辑

WITH relevant_tables AS (
  SELECT CONCAT(nspname, '.', relname) as table_name,
                 CONCAT('SELECT * FROM ', nspname, '.', relname) as table_query,
                 nspname as schema
      FROM pg_class c
      LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
      WHERE relkind = 'r'
      AND relname = 'users'
)
SELECT string_agg(table_query, ' UNION ALL ') as final_query
FROM relevant_tables a
LEFT JOIN (SELECT DISTINCT schema FROM tenants) b ON a.schema = b.schmea
WHERE b.schema IS NOT NULL
因此,即使使用
DO
块并将结果存储到表(
schema.table
)中,所有这些都是:


另一种解决方案甚至允许您将其作为查询运行,只需打印结果:

首先,运行此命令创建一个调用查询的函数(将
some\u schema
更改为可用于存储它的模式,将
some\u function\u name
更改为要使用的名称)。我不知道结果应该是什么样子,因为我没有看到您的数据,但是如果它是一个包含2个varchar列(
子域
名称
)的表,那么它将是这样的:

CREATE OR REPLACE FUNCTION some_schema.some_function_name()
returns TABLE(subdomain varchar(300), name varchar(300))
AS $BODY$
DECLARE
  stmt text;
  BEGIN
    stmt = (
      WITH relevant_tables AS (
        SELECT CONCAT(nspname, '.', relname) as table_name,
        CONCAT('SELECT * FROM ', nspname, '.', relname) as table_query,
        nspname as schema
        FROM pg_class c
        LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
        WHERE relkind = 'r'
        AND relname = 'users'
      )
      SELECT string_agg(table_query, ' UNION ALL ') as final_query
      FROM relevant_tables a
      LEFT JOIN (SELECT DISTINCT schema FROM tenants) b ON a.schema = b.schmea
      WHERE b.schema IS NOT NULL
    );
    return query EXECUTE stmt;
  end; $BODY$
language plpgsql
;
使用此功能后,您可以只运行:

select * from some_schema.some_function_name()
你应该看到你的结果


希望这能有所帮助。

所以您有50个同名的不同表,但每个表的模式不同?这是正确的。一分钟前实际上是97个模式。该网站的开发者使用了gem:@parfait-不幸的是,我只是在为一个现有的项目进行数据分析。我并不是受雇于一家上市公司开发的网站。如果我负责对这个网站进行分析,我会开发一个ETL流程,从每个模式中提取,并将其推到一个新的模式中,该模式具有相同的表,每个表都有一个额外的列来描述源模式。然后,我会在上面构建分析(也可以完全移动到另一个数据库)。然后你运行一个作业来保持所有的更新。@JuanCarlosOropeza-是的!如果我能弄明白的话,那正是我想要的。不是从pg_catalog.pg_表中选择*,而是我在问题中的一行给出了每个模式的名称。从租户中选择子域;添加新租户时会添加新架构,您需要一个动态查询这不会从表中获取架构名称
SELECT schema from tenants
。检查编辑:我离开了您的表,只获取了
tenants
对象中的架构名称。如何将do块添加到上面的代码中,因为这是最重要的部分?非常感谢你的帮助!定期添加和删除新的架构,不可能每次都有人手动编辑SQL查询。如果您希望执行此查询并将结果存储到某个表(
schema.table
)中,则只需将
string\u agg(table\u query,'UNION ALL')
替换为
CONCAT即可('DROP TABLE IF EXISTS schema.TABLE;CREATE TABLE schema.TABLE AS',string_agg(TABLE_query,'UNION ALL'))
。我认为您的最新评论是一个笑话,因为它建议您删除表。似乎有点混淆,这个问题是关于获取架构/表名称列表的。
select * from some_schema.some_function_name()