我正在尝试从使用原始SQL切换到SQLAlchemy / Flask-SQLAlchemy。据我学习简单查询,我无法理解如何使用子查询,嵌套连接和别名。
现在我有我的SQL查询:
SELECT device.*, wifi.name as room FROM
(SELECT * FROM devices WHERE mac="{0}") as device
LEFT JOIN
(SELECT w2.*, wifi_map.name as name FROM
(SELECT * FROM (SELECT * FROM wifi ORDER BY signal_pow DESC) as w1 GROUP BY device_id) as w2
INNER JOIN wifi_map
ON w2.bssid=wifi_map.bssid)
as wifi
ON device.id=wifi.device_id
我设法将LEFT JOIN
部分转换为SQLAlchemy(别名为wifi
的部分)。它看起来像这样:
sorted_wifi = db.session.query(WiFi).order_by(WiFi.signal_pow.desc())\
.join(WiFi.map).subquery()
wifi_with_room = db.session.query().add_entity(WiFi, alias=sorted_wifi)\
.group_by('device_id')
因此,此处wifi_with_room
是包含模型Wifi
和WiFi.map
的行列表,作为匹配的模型列表WiFiMap
(基于WiFi.bssid == WiFiMap.bssid
)。但我不知道我应该如何与wifi_with_room
一起加入Device
。我试过了
db.session.query(Device).outerjoin(wifi_with_room)
但这给了我错误
每个派生表都必须有自己的别名
然后我尝试了
db.session.query(Device).outerjoin(wifi_with_room.alias('wifi'))
但它返回了
AttributeError:'Query'对象没有属性'alias'
我想要实现的是具有以下内容的行列表:
Device
(及其所有元素)Device.room
然后WiFiMap.name
从WiFi.device_id == Device.id
返回的WiFiMap.bssid == WiFi.bssid
房间名称中的以下是我的模特:
class Device(db.Model):
__tablename__ = 'devices'
id = db.Column(db.Integer, primary_key=True)
mac = db.Column(db.Text)
vendor = db.Column(db.Text)
model = db.Column(db.Text)
name = db.Column(db.Text)
resolution_h = db.Column(db.Integer)
resolution_w = db.Column(db.Integer)
system_version = db.Column(db.Text)
cpu_model = db.Column(db.Text)
gpu = db.Column(db.Text)
gpu_clock = db.Column(db.Integer)
ram = db.Column(db.Integer)
layouts = db.Column(db.Text)
screen_size = db.Column(db.Float)
screen_density = db.Column(db.Integer)
imei = db.Column(db.Integer)
density_cat = db.Column(db.Text)
graphics_cat = db.Column(db.Text)
type = db.Column(db.Text)
last_active = db.Column(db.DateTime, onupdate=datetime.datetime.now)
unavailable = db.Column(db.Integer)
class WiFi(db.Model):
__tablename__ = 'wifi'
id = db.Column(db.Integer, primary_key=True)
device_id = db.Column(db.Integer, db.ForeignKey('devices.id', onupdate="CASCADE", ondelete="CASCADE"), index=True)
bssid = db.Column(db.String(17), index=True)
ssid = db.Column(db.Text)
signal_pow = db.Column(db.Integer)
class WiFiMap(db.Model):
__tablename__ = 'wifi_map'
room = db.Column(db.Integer)
x = db.Column(db.Integer)
y = db.Column(db.Integer)
bssid = db.Column(db.String(17), db.ForeignKey('wifi.bssid'), primary_key=True)
ssid = db.Column(db.Text)
name = db.Column(db.Text)
wifi = db.relationship('WiFi', backref='map', lazy='immediate')