2017-09-21 11 views
1

私は2つのテーブル、場所、場所_連絡先を持っています。最も小さい番号contact_id有するもの - - 一次コンタクトとみなされる左のジョインの注文結果が機能しない

mysql> describe locations; 
+----------------+----------------------------+------+-----+---------+----------------+ 
| Field   | Type      | Null | Key | Default | Extra   | 
+----------------+----------------------------+------+-----+---------+----------------+ 
| location_id | int(4)      | NO | PRI | NULL | auto_increment | 
| location_name | varchar(100)    | YES |  | NULL |    | 
+----------------+----------------------------+------+-----+---------+----------------+ 

mysql> describe locations_contacts; 
+---------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+---------------+--------------+------+-----+---------+----------------+ 
| contact_id | int(6)  | NO | PRI | NULL | auto_increment | 
| location_id | int(4)  | YES |  | NULL |    | 
| contact_name | varchar(100) | YES |  | NULL |    | 
+---------------+--------------+------+-----+---------+----------------+ 

各位置は、複数のコンタクトが、入力された最初のものを有することができます。私は単一のクエリでロケーション名とプライマリコンタクトを取得できるようにしたい。これは最初に働いたものです:

select a.location_id, a.location_name, b.contact from locations as a 
    left join (
     select location_id, contact_name as contact 
     from locations_contacts 
     group by location_id 
     ) as b on (a.location_id = b.location_id) 
where (location_name like '%wesleyan%' or contact like '%wesleyan%') 
order by location_name; 

問題は、locations_contactsの順序が一貫していないことです。 InnoDBを使用している間は問題ありませんでしたが、これはndbクラスタ設定でホストされています。左結合内で返される結果の順序が矛盾しているため、場所が複数ある場合は基本的にランダムな結果になります。左寄せで "order by"を使うと、順序付けができる前にグループ化が行われるので、group by節を削除することはできません。なぜなら、返される各位置に対して1つのレコードしか必要ないからです。

誰もがこれを手伝ってくれますか?私は最後の1日かそこそこで私の髪を引き裂いてきました。

+1

isPrimary列などを追加することはできませんか? – Nope

+0

それは可能ですが、私はそれが最後の手段であることを望みます。私はこのような問題がどこかで起こった場合にこのように解決することを望んでいました。 – loungehead

答えて

2

ここでは2つの結合が必要です。最初のものは、あなたの質問にあったのと同様のサブクエリに参加します。違いは、各場所で最低のcontact_idが見つかりました。しかし、あなたはcontact_nameを持ち込むためにlocations_contactsテーブルへの別の結合を行うことができるように、IDではなく連絡先の名前が必要です。

select 
    a.location_id, 
    a.location_name, 
    c.contact_name 
from locations as a 
left join 
(
    select location_id, min(contact_id) as min_contact_id 
    from locations_contacts 
    group by location_id 
) as b 
    on a.location_id = b.location_id 
inner join locations_contacts c 
    on b.location_id = c.location_id and 
     c.contact_id = b.min_contact_id 
where 
    a.location_name like '%wesleyan%' or 
    c.contact_name like '%wesleyan%' 
order by a.location_name; 
0

これは最もクリーンな解決策ではありませんが、2つの結合で行うことは可能です。最初はグループの最小値を取得し、2番目は連絡先を取得します。次のようなものがあります:

select a.location_id, a.location_name, c.contact from locations as a 
    left join (
     select location_id, min(contact_id) 
     from locations_contacts 
     group by location_id 
     ) as b on (a.location_id = b.location_id) 
    left join (
     select contact_name as contact 
     from locations_contacts 
     ) as c on (b.location_id = c.location_id and b.contact_id = c.contact_id) 
where (location_name like '%wesleyan%' or contact like '%wesleyan%') 
order by location_name; 
関連する問題