簡體   English   中英

Sqlalchemy單個查詢一個表中一列的多行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM