我在SQLAlchemy中使用Python(在我的特定情况下使用GeoAlchemy),并且我有一个查询导致一列行对象。我希望从这些行对象中提取特定值,但SQLAlchemy将行对象解释为单个实体(如果我是正确的,则将它们作为字符串返回)。如果不在Python中解析它们,我怎样才能更清晰地获得这些单个值呢?
我的真实用例:
PostgreSQL的PostGIS扩展提供了一个名为ST_IsValidDetail
的函数。此函数旨在返回valid_detail
行,其中包含布尔valid
,字符串reason
和无效的几何location
。我已经离开了PostGIS标签,因为我觉得这个问题比这更普遍。我的查询类似于SELECT ST_IsValidDetail('POINT(1 1)'::GEOMETRY);
(当然,几何形状更复杂)。
答案 0 :(得分:2)
您可以使用:
SELECT (ST_IsValidDetail(the_value)).* FROM the_table;
...但遗憾的是PostgreSQL实际上为每一行执行了一次ST_IsValidDetail
函数。作为一种解决方法,您可以更多地查询查询,通过公共表表达式实现,然后在第二遍中提取元组:
WITH interim_result(v) AS (
SELECT ST_IsValidDetail(the_value) FROM the_table
)
SELECT (v).* FROM interim_result;
(v)
周围的parens需要告诉解析器你引用的是一个值,而不是表名。
演示:
CREATE OR REPLACE FUNCTION multirows(x IN integer, a OUT integer, b OUT integer, c OUT integer) AS
$$
BEGIN
RAISE NOTICE 'multirows(%) invoked', x;
a := x;
b := x+1;
c := x+2;
RETURN;
END;
$$ LANGUAGE plpgsql;
craig=> SELECT multirows(x) FROM generate_series(1,2) x;
NOTICE: multirows(1) invoked
NOTICE: multirows(2) invoked
multirows
-----------
(1,2,3)
(2,3,4)
(2 rows)
craig=> SELECT (multirows(x)).* FROM generate_series(1,2) x;
NOTICE: multirows(1) invoked
NOTICE: multirows(1) invoked
NOTICE: multirows(1) invoked
NOTICE: multirows(2) invoked
NOTICE: multirows(2) invoked
NOTICE: multirows(2) invoked
a | b | c
---+---+---
1 | 2 | 3
2 | 3 | 4
(2 rows)
craig=> WITH interim(v) AS (SELECT multirows(x) FROM generate_series(1,2) x)
SELECT (v).* FROM interim;
NOTICE: multirows(1) invoked
NOTICE: multirows(2) invoked
a | b | c
---+---+---
1 | 2 | 3
2 | 3 | 4
(2 rows)
答案 1 :(得分:2)
我找到了一种从ST_IsValidDetail
页面上的示例中获取的方法。显然,以下语法有效:
SELECT gid, reason(ST_IsValidDetail(the_geom)), ST_AsText(location(ST_IsValidDetail(the_geom)))
请注意函数调用附带的reason
和location
“调用”; ST_IsValidDetail
返回的行中列的名称几乎与函数一样。事实证明,你可以欺骗SQLAlchemy做同样的事情。 (假设session
是先前设置的Session
对象,db_geom
是GeoAlchemy几何对象。)
from sqlalchemy import func as sqlfunc
result = session.query(sqlfunc.reason(sqlfunc.ST_IsValidDetail(db_geom)), sqlfunc.ST_AsText(sqlfunc.location(sqlfunc.ST_IsValidDetail(db_geom)))).one()
result[0]
将包含原因,result[1]
将包含该位置的WKT。 (我们可以使用label
为列提供实际名称。)
在不使用PostGIS功能的情况下将其修剪:
from sqlalchemy import func as sqlfunc
result = session.query(sqlfunc.columnname(sqlfunc.myrowfunc('some input string')).label('mylabel')).one()
这使得SQLAlchemy认为columnname
是一个函数,并以表格
SELECT columnname(myrowfunc('some input string')) AS mylabel;
我还没有尝试过,但是如果有办法让SQLAlchemy认为我们的行是我们选择FROM
的表,那么这也可能有用。 (请参阅ST_IsValidDetail
页面的最底部。)