Python 编写引用同一表两次的SQL查询
考虑下表中的定义Python 编写引用同一表两次的SQL查询,python,sqlite,database-design,orm,sqlalchemy,Python,Sqlite,Database Design,Orm,Sqlalchemy,考虑下表中的定义 class MCastSession(Base): __tablename__ = 'mcast_session' id = Column(Integer, primary_key=True) ip = Column(Integer) port = Column(Integer) __table_args__ = ( UniqueConstraint('ip', 'port'), ) class Topic(Base): __tablename__ =
class MCastSession(Base):
__tablename__ = 'mcast_session'
id = Column(Integer, primary_key=True)
ip = Column(Integer)
port = Column(Integer)
__table_args__ = ( UniqueConstraint('ip', 'port'), )
class Topic(Base):
__tablename__ = 'topic'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
mcast_session_id = Column(Integer, ForeignKey('mcast_session.id'))
mcast_session = relationship('MCastSession')
class Host(Base):
__tablename__ = 'host'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
class Subscriber(Base):
__tablename__ = 'subscriber'
id = Column(Integer, primary_key=True)
topic_id = Column(Integer, ForeignKey('topic.id'))
topic = relationship('Topic')
host_id = Column(Integer, ForeignKey('host.id'))
host = relationship('Host')
__table_args__ = ( UniqueConstraint('topic_id', 'host_id'), )
Example data:
Topic Session
T1 IP1:port1
T2 IP1:port2
T3 IP1:port2
T4 IP2:port1
Topic Host
T1 H1
T2 H1
T4 H2
我想编写一个查询,以获取订阅多播ip但不处理ip的所有主题的所有主机。在上面的例子中。H1有T1,因此订阅IP1,但没有T3,也有相同的IP1。因此查询应该返回H1。H2处理其订阅的IP(T4)的所有主题(T4),因此H2不应出现在结果中。如何为上述内容编写查询 下面的查询将生成目标:
select distinct host1.name host_name
from Subscriber Subscriber1
inner join host host1
on host1.id = Subscriber1.Host_Id
inner join topic topic1
on topic1.id = Subscriber1.Topic_Id
inner join mcast_session mcast_session1
on mcast_session1.id = topic1.mcast_session_id
where (select count(*)
from mcast_session
where mcast_session.ip = mcast_session1.ip) !=
(select count(*)
from topic
inner join mcast_session
on topic.mcast_session_id = mcast_session.id
where mcast_session.ip = mcast_session1.ip)
对于逻辑的解释,查询可能有助于:
select host1.name host_name,
topic1.name topic_name,
mcast_session1.ip,
mcast_session1.port,
(select count(*)
from mcast_session
where mcast_session.ip = mcast_session1.ip) host_to_topic_registeration,
(select count(*)
from topic
inner join mcast_session
on topic.mcast_session_id = mcast_session.id
where mcast_session.ip = mcast_session1.ip
) ip_topic_count
from Subscriber Subscriber1
inner join host host1
on host1.id = Subscriber1.Host_Id
inner join topic topic1
on topic1.id = Subscriber1.Topic_Id
inner join mcast_session mcast_session1
on mcast_session1.id = topic1.mcast_session_id
:查看所需结果的另一种方法是应用以下逻辑:
IP
地址,计算主题的总数
主机
计算按IP
地址分组的主题
广播的总数IP
地址的主题数不等于IP
地址总数的主机
主机
实例:
它生成下面的SQL
代码(对于SQLite
):
现在,如果要在查询中多次使用同一个表,可以使用。下面的代码将返回元组列表
(mcasession,NNN)
,其中NNN
是具有相同IP
的MCastSession对象数:
aliased_MCastSession = aliased(MCastSession, name="MCastSession2")
qry = session.query(\
MCastSession, \
func.count(aliased_MCastSession.id).label("number_with_same_ip")).\
filter(MCastSession.ip == aliased_MCastSession.ip).\
group_by(MCastSession)
但是我不需要为提出的解决方案这样做,因为我使用了子查询。如果有人可以帮助只使用原始SQL查询,这也将有助于两次引用同一个表:
从my_选项卡中选择一个*作为第一个_引用将my_选项卡作为第一个_引用的第二个_引用加入my_选项卡。ID=second_reference.ID+1
SELECT host.id AS host_id, host.name AS host_name
FROM host
JOIN (SELECT host.id AS host_id,
mcast_session.ip AS mcast_session_ip,
count(topic.id) AS num_topics
FROM host
JOIN subscriber
ON host.id = subscriber.host_id
JOIN topic
ON topic.id = subscriber.topic_id
JOIN mcast_session
ON mcast_session.id = topic.mcast_session_id
GROUP BY host.id, mcast_session.ip
) AS host_ip_topics
ON host.id = host_ip_topics.host_id
JOIN (SELECT mcast_session.ip AS mcast_session_ip,
count(topic.id) AS num_topics
FROM mcast_session
JOIN topic
ON mcast_session.id = topic.mcast_session_id
GROUP BY mcast_session.ip
) AS ip_topics
ON host_ip_topics.mcast_session_ip = ip_topics.mcast_session_ip
AND host_ip_topics.num_topics != ip_topics.num_topics
aliased_MCastSession = aliased(MCastSession, name="MCastSession2")
qry = session.query(\
MCastSession, \
func.count(aliased_MCastSession.id).label("number_with_same_ip")).\
filter(MCastSession.ip == aliased_MCastSession.ip).\
group_by(MCastSession)