[英]Sqlalchemy single query for multiple rows from one column in one table
我遇到過sqlite3和sqlalchemy的一些問題。 從一段時間以來,我嘗試進行一些特定的查詢,並在某種程度上我失敗了。 數據庫由兩個表用戶和Properties組成。 這些表具有如下所示的模式。
sqlite> .schema users
CREATE TABLE users (
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);
sqlite> .schema properties
CREATE TABLE properties (
id INTEGER NOT NULL,
property_number INTEGER,
user_id INTEGER,
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES users (id)
);
用戶表的內容非常簡單,但屬性值得一些解釋。 在property_number列中,我存儲了不同的屬性,每個屬性都有唯一的編號,例如:property bald的編號為3,屬性tan的編號為4等。如果User有多個屬性,則每個屬性都占用屬性表中的一行。 我選擇這種樣式以便於添加新屬性,而不會弄亂遷移和類似的東西。
問題是,不知道如何進行包含多個屬性的查詢。 我目前最好的解決方案是,在單獨的查詢中詢問每個屬性。 這給出了mi的集合列表,兩個不同的集合。 一個用於給定屬性的正面和一個用於負面實例(正面等於我希望用戶擁有的東西,負面等於我不希望用戶擁有的東西)。 在下一步中,我將兩個子集區分開來,並獲得最終列表,其中包含對我有興趣的用戶ID。 然后我查詢這些用戶的名字。 這似乎很復雜,也許是,但肯定是丑陋的。 我也不喜歡對每個屬性進行單一查詢。 Python代碼,如果somone感興趣。
def prop_dicts():
"""Create dictionaries of properties
contained in table properties in db.
Returns:
touple:
prop_names (dict)
prom_values (dict)."""
prop_names = {'higins': 10000,
'tall': 1,
'fat': 2,
'bald': 3,
'tan': 4,
'hairry': 5}
prop_values = {1000: 'higins',
1: 'tal',
2: 'fat',
3: 'bald',
4: 'tan',
5: 'hairry'}
dictionaries = (prop_names, prop_values)
return dictionaries
def list_of_sets_intersection(set_list):
"""Makes intersection of all sets in list.
Args:
param1 (list): list containing sets to check.
Returns:
set (values): contains intersectred values."""
if not set_list:
return set()
result = set_list[0]
for s in set_list[1:]:
result &= s
return result
def list_of_sets_union(set_list):
"""Makes union of elements in all sets in list.
Args:
param1 (list): list containing sets to check.
Returns:
set (values): contains union values."""
if not set_list:
return set()
result = set_list[0]
for s in set_list[1:]:
result |= s
return result
def db_search():
"""Search database against positiv and negative values.
Returns:
list (sets): one set in list for every property in
table properties db."""
n, v = prop_dicts()
positive = [2, 3]
negative = [4, 5]
results_p = []
results_n = []
#Positive properties.
for element in xrange(0, len(positive)):
subresult = []
for u_id, in db.query(Property.user_id).\
filter_by(property_number = positive[element]):
subresult.append(u_id)
subresult = set(subresult)
results_p.append(subresult)
#Negative properties.
for element in xrange(0, len(negative)):
subresult = []
for u_id, in db.query(Property.user_id).\
filter_by(property_number = negative[element]):
subresult.append(u_id)
subresult = set(subresult)
results_n.append(subresult)
print 'positive --> ', results_p
print 'negative --> ', results_n
results_p = list_of_sets_intersection(results_p)
results_n = list_of_sets_union(results_n)
print 'positive --> ', results_p
print 'negative --> ', results_n
final_result = results_p.difference(results_n)
return list(final_result)
print db_search()
這是一種在單個查詢中執行此操作的方法嗎? 我是數據庫領域的新手,對不起,如果問題的質量似乎很蹩腳。 有很多可能性,我真的不知道如何以“正確”的方式做到這一點。 我已經搜索了大量關於這個主題的互聯網,我找到的最佳解決方案是包含“WHERE”原因和“AND”運算符。 但是如果你連接兩個相同的一個表列,那么這兩個不起作用。
SELECT user_id FROM properties WHERE property_number=3 AND property_number=4;
或者在sqlalchemy。
db.query(User.user_id).join(Property).filter(and_(property_number=3, property_number=4)).all()
這個sqlalchemy示例可能包含一些錯誤,因為我沒有預覽,但肯定你會明白這是什么意思。
您可以使用聚合來完成此操作
SELECT user_id
FROM properties
WHERE property_number in (3, 4)
GROUP BY user_id
HAVING count(*) = 2
在SQLAlchemy中
from sqlalchemy import func
properties = [3, 4]
db.session.query(Property.user_id)\
.filter(Property.property_number.in_(properties))\
.group_by(Property.user_id)\
.having(func.count()==len(properties))\
.all()
更新
positive = [2, 3]
negative = [4, 5]
positive_query = db.session.query(Property.user_id)\
.filter(Property.property_number.in_(positive))\
.group_by(Property.user_id)\
.having(func.count()==len(positive))
negative_query = db.session.query(Property.user_id)\
.filter(Property.property_number.in_(negative))\
.distinct()
final_result = positive_query.except_(negative_query).all()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.