まず、一歩前に戻ってSQLを見てください。あなたの現在のクエリは制限がa JOIN b
ないa
にある
SELECT * FROM a JOIN b ON b.id_a = a.id WHERE b.name == '...' LIMIT 50;
お知らせですが、a
に制限を置く場合は、b
のフィールドでフィルタすることはできません。この問題には2つの解決策があります。
SELECT * FROM a
WHERE EXISTS (SELECT 1 FROM b WHERE b.id_a = a.id AND b.name = '...')
LIMIT 50;
これは、DBのバックエンドに依存して非効率的であることができる:最初はこのように、b.name
にフィルタリングするスカラーサブクエリを使用することです。第2の解決策は、参加した後、このように、a
にDISTINCTを行うことです。どちらの場合にはあなたがb
から任意の列を得ることはありませんどのように
SELECT DISTINCT a.* FROM a JOIN b ON b.id_a = a.id
WHERE b.name == '...'
LIMIT 50;
注意してください。どうやって入手するのですか?別の参加をしてください!今
SELECT * FROM (
SELECT DISTINCT a.* FROM a JOIN b ON b.id_a = a.id
WHERE b.name == '...'
LIMIT 50;
) a JOIN b ON b.id_a = a.id
WHERE b.name == '...';
は、SQLAlchemyの中でこのすべてを書き込みます:
好奇心のうち
subquery = (
session.query(A)
.join(B)
.with_entities(A) # only select A's columns
.filter(B.name == '...')
.distinct()
.limit(50)
.subquery() # convert to subquery
)
aliased_A = aliased(A, subquery)
query = (
session.query(aliased_A)
.join(B)
.options(contains_eager(aliased_A.children))
.filter(B.name == "...")
)
、例えば、(おそらくセミ結合として計画された)が存在する使用してから何DBバックエンドを被ります。 –
@IljaEveriläこれは、データベースエンジン、バージョン、クエリなどの複数の要素に大きく依存するものの1つで、直接的な回答を与えるのは難しいです。 *一般的な意味では、サブクエリよりもジョインは通常は*より効率的です。いつものように、それを把握するためのプロファイル。 – univerio
それはちょうど事であり、EXISTSは、少なくともいくつかのdbsでは、セミジョインとして実装でき、実装されています。もちろん、それはすべてのクエリには当てはまらないかもしれませんが、通常この種の単純なケースで起こります。しかし、結局私はあなたがお金にちょうど良いと思う:プロフィールと参照してください。 –