私は次のような問題のように簡略化することができ抽象的な問題を抱えている:この結果を得るためにMySQL SELECTクエリを書くには?
SELECT * FROM persons;
+----+-------+--------+
| id | name | fan_of |
+----+-------+--------+
| 1 | alice | 2 |
| 2 | bob | 4 |
| 3 | carol | 1 |
| 4 | dave | 3 |
| 5 | bob | 2 |
+----+-------+--------+
と
SELECT * FROM names;
+----+-------+--------+
| id | name | active |
+----+-------+--------+
| 1 | alice | 1 |
| 2 | bob | 1 |
| 3 | carol | 0 |
| 4 | dave | 1 |
+----+-------+--------+
すべての人(行を次のように私たちが見て二つのテーブルpersons
とnames
を持っていると仮定persons
)テーブルは、それ自体または他の人のファンである(列の他の人id
によって表される)。 names
テーブルには、アクティブまたは非アクティブの名前が含まれています。与えられたために
はk
オフセット、私は彼らの名前としてk+1
番目のアクティブな名前を持っているか、その彼らのファンとして、これらの人々のいずれかを持っている人(persons
の行を)SELECT
したいです。たとえば、オフセットが1の場合、2番目のアクティブな名前はbobです。したがって、名前がbobのすべての人と、これらのbobをファンとして持つ人を選択したいとします。この例では、 id
= 4。これは私が結果を持ってしたいことを意味します
+----+------+--------+
| id | name | fan_of |
+----+------+--------+
| 2 | bob | 4 |
| 4 | dave | 3 |
| 5 | bob | 2 |
+----+------+--------+
私がこれまで持っていることは、次のクエリです:
1 SELECT * FROM persons WHERE
2 EXISTS (
3 SELECT * FROM (
4 SELECT * FROM names WHERE active=true LIMIT 1 OFFSET 1
5 ) AS selectedname WHERE (selectedname.name=persons.name)
6 )
7 OR
8 EXISTS (
9 SELECT * FROM(
10 SELECT * FROM persons WHERE EXISTS (
11 SELECT * FROM (
12 SELECT * FROM names WHERE active=true LIMIT 1 OFFSET 1
13 ) AS selectedname WHERE (selectedname.name=persons.name)
14 )
15 ) AS personswiththatname WHERE persons.id=personswiththatname.fan_of
16 );
それは上から私に望ましい結果を与えるが、それがあるため非効率的であることに注意してください3-5行目と11-13行目は同じです。
I持って、次の二つの質問:
-
この非効率性を回避するために何ができるか
- ?
私は実際に
name
条件(名前=ボブとここに行)とfan_of
条件(名前=デイブとこちら行)から を来たものから来て、これらの行を区別する必要があります。この はアプリケーションコードで実行できますが、番目のアクティブな名前を調べるにはもう一度 データベースクエリが必要です。これは が遅くなる可能性があります(この方が良い解決策であれば修正してください)。私は むしろ、私がどのような出力を達成することができる
のように区別するのに役立ちます追加の列+----+------+--------+---+ | id | name | fan_of | z | +----+------+--------+---+ | 2 | bob | 4 | 1 | | 4 | dave | 3 | 0 | | 5 | bob | 2 | 1 | +----+------+--------+---+
z
を好むでしょうか?
を" "与えられたオフセットkに対して、k + 1番目のアクティブな名前を持つ人物(人物の行)を選んで、その人物の1人をファンとして " 実際には、k + 1番目のアクティブな名前を持つ人物、またはその名前の別の人物のファンである人物を選択したいとは限りません。 あなたの説明が私にとって意味をなさない唯一の方法です。 –
@ChrisJいいえ、それは言いましたが、それは現実の例として意味をなさないと認めます。私が望むのは、その名前を持つすべての人と 'fan_of'カラムによって参照されるすべての人です。 – phinz
Bobは彼のファンであり、Bobはn番目の(選択された)アクティブな名前なので、「Dave」が取得されますか? –