我构建了一个sql子句,我在其中引用了与a
和b
相同的表来将两个几何比较为postgis命令。
我想使用%s
运算符将值传递给sql语句,并使用to_sql, params kwargs
将结果读入pandas数据帧。目前我的代码将允许将一个值传递给一个%s
,但我正在寻找同一个值列表的多个插入。
我正在使用psycopg2连接到postgresql数据库。
简化代码在
之下sql = """
SELECT
st_distance(a.the_geom, b.the_geom, true) AS dist
FROM
(SELECT
table.*
FROM table
WHERE id in %s) AS a,
(SELECT
table.*
FROM table
WHERE id in %s) AS b
WHERE a.nid <> b.nid """
sampList = (14070,11184)
df = pd.read_sql(sql, con=conn, params = [sampList])
基本上我想在两个地方用sampList值替换%s
。写入的代码只会替换表示': list index out of range
的第一个值。如果我调整为使用一个%s
并用代码运行的数字替换第二个语句,但最终我希望重复这些值。
答案 0 :(得分:1)
您不需要子查询,只需将表连接到自身:
SELECT a.*, b.* -- or whatwever
, st_distance(a.the_geom, b.the_geom, true) AS dist
FROM ztable a
JOIN ztable b ON a.nid < b.nid
WHERE a.id IN (%s)
AND b.id IN (%s)
;
避免使用CTE重复(这可能是非最佳的,性能方面的)
WITH zt AS (
SELECT * FROM ztable
WHERE id IN (%s)
)
SELECT a.*, b.* -- or whatever
, st_distance(a.the_geom, b.the_geom, true) AS dist
FROM zt a
JOIN zt b ON a.nid < b.nid
;
在性能方面,我会坚持使用第一个版本,并提供两次list-argument。 (或使用FORMAT()构造引用它两次
答案 1 :(得分:0)
首先,我建议您使用updated SQL from @wildplasser - 这是更好,更有效的方法。
现在您可以执行以下操作:
sql_ = """\
WITH zt AS (
SELECT * FROM ztable
WHERE id IN ({})
)
SELECT a.*, b.* -- or whatever
, st_distance(a.the_geom, b.the_geom, true) AS dist
FROM zt a
JOIN zt b ON a.nid < b.nid
"""
sampList = (14070,11184)
sql = sql_.format(','.join(['?' for x in sampList]))
df = pd.read_sql(sql, con=conn, params=sampList)
动态生成带参数的SQL(AKA:预处理语句,绑定变量等):
In [27]: print(sql)
WITH zt AS (
SELECT * FROM ztable
WHERE id IN (?,?)
)
SELECT a.*, b.* -- or whatever
, st_distance(a.the_geom, b.the_geom, true) AS dist
FROM zt a
JOIN zt b ON a.nid < b.nid