在 JOIN 之外引用 SELECT
Refer to SELECT outside of JOIN
我在 my previous question 中得到了一些很大的帮助。这个建立在那个之上。我想检索连接查询的信息,但我不知道在 SQL.
中是否可行
这是一个包含平民的虚拟数据库。每行包含他们的姓名、城市、街道、街道号码和工作。在 SQLite:
中生成数据库的最小示例
import sqlite3
from pathlib import Path
def main():
build_cmd = """CREATE TABLE civs (
name TEXT,
city TEXT,
street TEXT,
snumber INTEGER,
job TEXT) """
pdb = Path("dummy.db")
if pdb.exists():
pdb.unlink()
conn = sqlite3.connect(str("dummy.db"))
cur = conn.cursor()
cur.execute(build_cmd)
insert_cmds = """
BEGIN TRANSACTION;
INSERT INTO civs VALUES ('john', 'dublin', 'butchers_street', '42', 'butcher');
INSERT INTO civs VALUES ('marie', 'london', 'butchers_street', '3', 'baker');
INSERT INTO civs VALUES ('keith', 'london', 'camel_road', '7', 'carpenter');
INSERT INTO civs VALUES ('anna', 'dublin', 'butchers_street', '9', 'butcher');
INSERT INTO civs VALUES ('steve', 'london', 'maceys_alley', '1', 'blacksmith');
INSERT INTO civs VALUES ('beth', 'dublin', 'butchers_street', '68', 'grocer');
INSERT INTO civs VALUES ('lisa', 'dublin', 'church_street', '32', 'nun');
COMMIT;
"""
cur.executescript(insert_cmds)
cur.close()
conn.commit()
conn.close()
if __name__ == '__main__':
main()
假设我想检索一行(所以住在约翰街的每个人一行)。我使用“一个”约翰,因为理论上你当然可以有多个约翰。
- 约翰住的街道
- 约翰居住的城市
- 约翰的工作
- 与约翰住在同一条街道和城市的人的名字
- 与约翰住在同一条街道和城市的人的工作
到此为止,它检索了主查询的信息。
SELECT
civs.street, civs.city, civs.name, civs.job
FROM civs
JOIN
(SELECT city, street
FROM civs
WHERE name='john') jcivs
ON civs.street = jcivs.street
AND civs.city = jcivs.city
这给出了
street
city
name
job
butchers_street
dublin
anna
butcher
butchers_street
dublin
beth
grocer
butchers_street
dublin
john
butcher
但是“John 的工作”严重缺失 并且 我将 john 作为单独的一行,我不想要它,因为我们对 John 的邻居感兴趣。所以我不确定如何从最外层 SELECT 引用 jcivs
。所以这不起作用,因为 jcivs
对于外部 SELECT:
不存在
SELECT
civs.street, civs.city, jcivs.job, civs.name, civs.job
预期结果:
street
city
johnsjob
name
job
butchers_street
dublin
butcher
anna
butcher
butchers_street
dublin
butcher
beth
grocer
注意:效率对我来说很重要。您可以假设它是冷的 table 并且所有列都已编入索引。
这应该是一种方法:
WITH civs2 AS (
SELECT civs.*, row_number() OVER () as id FROM civs
)
SELECT
civs2.street, civs2.city, jcivs.job, civs2.name, civs2.job
FROM civs2
JOIN
(SELECT city, street, job, id
FROM civs2
WHERE name='john') jcivs
ON civs2.street = jcivs.street
AND civs2.city = jcivs.city
AND civs2.id <> jcivs.id
根据您的查询,我们:
- 将作业添加到 jcivs 子查询;和
- 通过创建一个带有基于行号的 ID 的 CTE 来演示 ID 的使用。然后,我们确保
civs.id <> jcivs.id
如果您有 table 的 ID,那可能会更有效,因为我们可以将其添加到连接 civs.id <> jcivs.id
。
不需要创建 id
列,因为 SQLite 为每个 table 提供了一个 rowid
列(这是 table 的实际主键) .
像这样做一个简单的自连接:
SELECT c1.*
FROM civs c1 INNER JOIN civs c2
ON (c2.city, c2.street) = (c1.city, c1.street) AND c2.rowid <> c1.rowid
WHERE c2.name = 'john';
参见demo。
我在 my previous question 中得到了一些很大的帮助。这个建立在那个之上。我想检索连接查询的信息,但我不知道在 SQL.
中是否可行这是一个包含平民的虚拟数据库。每行包含他们的姓名、城市、街道、街道号码和工作。在 SQLite:
中生成数据库的最小示例import sqlite3
from pathlib import Path
def main():
build_cmd = """CREATE TABLE civs (
name TEXT,
city TEXT,
street TEXT,
snumber INTEGER,
job TEXT) """
pdb = Path("dummy.db")
if pdb.exists():
pdb.unlink()
conn = sqlite3.connect(str("dummy.db"))
cur = conn.cursor()
cur.execute(build_cmd)
insert_cmds = """
BEGIN TRANSACTION;
INSERT INTO civs VALUES ('john', 'dublin', 'butchers_street', '42', 'butcher');
INSERT INTO civs VALUES ('marie', 'london', 'butchers_street', '3', 'baker');
INSERT INTO civs VALUES ('keith', 'london', 'camel_road', '7', 'carpenter');
INSERT INTO civs VALUES ('anna', 'dublin', 'butchers_street', '9', 'butcher');
INSERT INTO civs VALUES ('steve', 'london', 'maceys_alley', '1', 'blacksmith');
INSERT INTO civs VALUES ('beth', 'dublin', 'butchers_street', '68', 'grocer');
INSERT INTO civs VALUES ('lisa', 'dublin', 'church_street', '32', 'nun');
COMMIT;
"""
cur.executescript(insert_cmds)
cur.close()
conn.commit()
conn.close()
if __name__ == '__main__':
main()
假设我想检索一行(所以住在约翰街的每个人一行)。我使用“一个”约翰,因为理论上你当然可以有多个约翰。
- 约翰住的街道
- 约翰居住的城市
- 约翰的工作
- 与约翰住在同一条街道和城市的人的名字
- 与约翰住在同一条街道和城市的人的工作
到此为止,它检索了主查询的信息。
SELECT
civs.street, civs.city, civs.name, civs.job
FROM civs
JOIN
(SELECT city, street
FROM civs
WHERE name='john') jcivs
ON civs.street = jcivs.street
AND civs.city = jcivs.city
这给出了
street | city | name | job |
---|---|---|---|
butchers_street | dublin | anna | butcher |
butchers_street | dublin | beth | grocer |
butchers_street | dublin | john | butcher |
但是“John 的工作”严重缺失 并且 我将 john 作为单独的一行,我不想要它,因为我们对 John 的邻居感兴趣。所以我不确定如何从最外层 SELECT 引用 jcivs
。所以这不起作用,因为 jcivs
对于外部 SELECT:
SELECT
civs.street, civs.city, jcivs.job, civs.name, civs.job
预期结果:
street | city | johnsjob | name | job |
---|---|---|---|---|
butchers_street | dublin | butcher | anna | butcher |
butchers_street | dublin | butcher | beth | grocer |
注意:效率对我来说很重要。您可以假设它是冷的 table 并且所有列都已编入索引。
这应该是一种方法:
WITH civs2 AS (
SELECT civs.*, row_number() OVER () as id FROM civs
)
SELECT
civs2.street, civs2.city, jcivs.job, civs2.name, civs2.job
FROM civs2
JOIN
(SELECT city, street, job, id
FROM civs2
WHERE name='john') jcivs
ON civs2.street = jcivs.street
AND civs2.city = jcivs.city
AND civs2.id <> jcivs.id
根据您的查询,我们:
- 将作业添加到 jcivs 子查询;和
- 通过创建一个带有基于行号的 ID 的 CTE 来演示 ID 的使用。然后,我们确保
civs.id <> jcivs.id
如果您有 table 的 ID,那可能会更有效,因为我们可以将其添加到连接 civs.id <> jcivs.id
。
不需要创建 id
列,因为 SQLite 为每个 table 提供了一个 rowid
列(这是 table 的实际主键) .
像这样做一个简单的自连接:
SELECT c1.*
FROM civs c1 INNER JOIN civs c2
ON (c2.city, c2.street) = (c1.city, c1.street) AND c2.rowid <> c1.rowid
WHERE c2.name = 'john';
参见demo。