2011-07-04 5 views
0

SELECT user_name, item_name FROM users, items WHERE users.favor_item_id = items.item_idという同等のクエリを実行したいと思います。これはuser_nameとitem_nameのペアを返します。データベースでは、1人のユーザーが複数のお気に入りアイテムを持つことができます。DjangoでデータベースJOINを実行中

私は、このSQLクエリと同等のDjangoクエリが何か不思議ですか?

私の最初の考えは、すべての(user、favor_item_id)ペアをUSERSからリストし、item_idがitem_idであるitem_nameを探すことです。しかし、それはO(NlogM)の複雑さを持つITEMテーブルをN回(Nはペア数)検索します(MはITEMの項目数です)。上記のSQLクエリを使用すると、複雑さはOです(N)。

django(または任意のORMシステム)でこれを行うより効率的な方法がありますか?

+0

あなたの質問では、ユーザーの好きな項目は 'users'関係の列だと言いますが、まさに次の文で、ユーザーは複数のお気に入り項目を持つことができます。一人のユーザが 'users'テーブルに複数回出現することができない限り、それはどのように可能ですか? – SingleNegationElimination

答えて

2

(または任意のORMシステム)?

本当に?ここにあなたが(宣言型を使用して、ここでは)合理的なマッピングされたクラスを想定すると、SQLAlchemyの

でそれを行うだろう方法は次のとおりです。

Base = sqlalchemy.ext.declarative.declarative_base() 

class Item(Base): 
    __tablename__ = 'items' 
    id = Column('item_id', Integer, primary_key=True) 
    name = Column('item_name', String) 

class User(Base): 
    __tablename__ = 'users' 
    name = Column('user_name', String(50), primary_key=True) 
    favor_item_id = Column(Integer, ForeignKey(Item.id)) 

    favor_item = relationship(Item, backref="favored_by") 

クエリがモデルと仮定

>>> print sqlalchemy.orm.Query((User.name, Item.name)).join(Item.favored_by) 
SELECT users.user_name AS users_user_name, items.item_name AS items_item_name 
FROM items JOIN users ON items.item_id = users.favor_item_id 
1

超簡単です:

class User(models.Model): 
    name = models.CharField(max_length=32) 
    favorite = models.ForeignKey(Item) 

class Item(models.Model): 
    name = models.CharField(max_length=32) 

同等のDjangoは次のようになります。

usersFavorites = User.objects.all().values_list("name", "favorite__name") 

これは、指定したフィールドの正確な名前は使用しません。そのためには、適切なdb_tableフィールドとdb_columnフィールドをモデルに追加するだけです。

P.S.この特定のスキーマはあまり良くありません。アイテムのみForeignKeyItemであるべき場合には一人のユーザを有することができない限り

class User(models.Model): 
    name = models.CharField(max_length=32) 
    favorites = models.ManyToManyField(Item, related_name="users") 

class Item(models.Model): 
    name = models.CharField(max_length=32) 

:私見、UserItemは、多対多の関係を有していなければなりません。

その後、あなたは、二重ループで繰り返すことができますので、select_related()コールの

for user in User.objects.all().select_related("favorites"): 
    for favorite in user.favorites: 
     # use `user` and `favorite` in some way. 

、クエリが最初forループで一挙に行われます。

関連する問題