2016-07-01 3 views
1

私は今レンタルのプロセスを管理するシステムを開発していますが、現在レンタルしている人の名前ですべてのレンタル可能なオブジェクトを効率的に照会する方法オブジェクトが現時点でレンタルされているかどうか。さもなければ、その列にNULLがあるはずです。mysqlデータベースで1:n:1:1の関係に正しく結びついています

私のテーブルは次のようになります。

オブジェクト

| object_id | object_name | 
--------------------------- 
| 1   | Object A | 
| 2   | Object B | 
| 3   | Object C | 
| 4   | Object D | 
| 5   | Object E | 
--------------------------- 

| person_id | person_name | 
--------------------------- 
| 1   | John Doe | 
| 2   | Jane Doe | 
| 3   | Max Muster | 
| 4   | Foobar  | 
--------------------------- 

レンタル

| rental_id | rental_state| person_person_id | 
---------------------------------------------- 
| 1   | open  | 1    | 
| 2   | returned | 1    | 
| 3   | returned | 2    | 
| 4   | open  | 3    | 
| 5   | returned | 4    | 
---------------------------------------------- 

rental2object

| rental_rental_id | object_object_id | 
--------------------------------------- 
| 1    | 1    | 
| 2    | 2    | 
| 2    | 3    | 
| 3    | 3    | 
| 4    | 2    | 
| 4    | 5    | 
| 5    | 2    | 
--------------------------------------- 

私が望む結果は次のようになります。

| object_id | object_name | rented_to  | 
------------------------------------------- 
| 1   | Object A | John Doe  | 
| 2   | Object B | Max Muster | 
| 3   | Object C | NULL   | 
| 4   | Object D | NULL   | 
| 5   | Object E | Max Muster | 
------------------------------------------- 

私がこれまで持っていることは次のとおりです。

SELECT `object_id`, `object_name`, `person_name` FROM `object` 
LEFT JOIN `rental2object` ON `object_id` = `object_object_id` 
LEFT JOIN `rental` ON `rental_id` = `rental_rental_id` AND `rental_state` = 'open' 
LEFT JOIN `person` ON `person_id` = `person_person_id` 
GROUP BY `object_id` 

明白な問題ですグループ化している間に正しい方法を集める方法がわかりません。

私の目標を達成する最も効率的な方法は何でしょうか?あなたの助けに感謝。

EDIT

そのオブジェクトBはまた、最大ムスターにレンタルされているように、期待される結果を修正。

+0

をお試しください'SELECT'文中の' GROUP BY'には存在しない列です。 – ydoow

+1

オブジェクト#2と#5は両方ともレンタル#4にあります。しかし、あなたは期待どおりの結果を得るためには、両方の方法で処理します。オブジェクトEとオブジェクトBは、どちらも同じ動作でなければならず、両方とも関連していますMax Muster、それはありませんか?なぜオブジェクトBにNull related_to personがあるのですか? – danihp

+0

あなたの編集を確認してから、私の答えをチェックし、いくつかのmuggleから投票しました。理由はわかりません。ところで – danihp

答えて

1

ご質問について

#2と#5の両方のオブジェクトがレンタル#4にあります。しかし、あなたの期待した結果では、あなたは両方を異なる方法で処理しています。オブジェクトEとオブジェクトBは、同じレンタル内にあるため、両方とも同じ動作でなければなりません。もしそうでなければ、製品が関連する人物を持っているかどうかを知る基準は魔女の説明であるべきです。 SELECT句内のすべての非集約列が含まれるように、あなたがすべきSQL99準拠するために

SELECT `object_id`, `object_name`, `person_name` as rented_to 
FROM `object` 
... 
GROUP BY `object_id`, `object_name`, `person_name` 

SQL92準拠したあなたはselect句内のすべての非集約列を含めるべき的には

によって

グループあなたのケースでは、object_idとobject_nameの間に依存しています:object_id -> object_nameのフィールドRent_stateは機能に依存しません人)に、そしてあなただけ書くことができます。

SELECT `object_id`, `object_name`, `person_name` as rented_to 
FROM `object` 
... 
GROUP BY `object_id`, `person_name` 

のMySQL 5.7。5以降では関数依存の検出が実装されていますが、この最後の選択は有効ですが、わかりやすくするために、最初のものを使用することをお勧めします。

は、より多くの情報とONLY_FULL_GROUP_BYパラメータの詳細についてMySQL Handling of GROUP BY読みます。

  • オブジェクト::OBJECT_ID(その後、インデックスは暗黙的である、主キーである)
  • がrental2object:object_object_id(コンポジットかもしれ

    パフォーマンス

    はあなたのためにインデックスを持っていることを確認してください他のフィールドとインデックスが、object_object_idは、インデックスの最初のフィールドであることを確認してください)

  • レンタL:& rental_state(両方のフィールドを持つ複合インデックス)
  • をrental_id:PERSON_ID(主キーである場合、インデックスは暗黙的である)

+0

もう一度見てクエリがオブジェクトBの最後のステータスが返されますがのOPソリューションは、これが開いていて、最大ムスターに借り思っていることを期待した結果に基づいて、私は考えて所望の出力 –

+0

と一致していません。クエリはおそらく、オブジェクトの最後の状態を見つけるためにmaxのどこにテストが必要なのでしょうか?また、on節でテストするべきではありません。 –

+0

いいえ私はしませんでした.... –

-1

があり、この

SELECT 
    o.object_id, 
    o.object_name, 
    p.person_name AS rent_to 
FROM 
    rental2object ro 
RIGHT JOIN object o ON ro.object_object_id = o.object_id 
LEFT JOIN rental r ON ro.rental_rental_id = r.rental_id AND r.rental_status = 'open' 
JOIN person p ON r.person_person_id = p.person_id 
+0

は正しくありません。オブジェクトへの結合は、すべてのオブジェクトを選択するための '右外部結合 'でなければなりません。 – danihp

+0

@danihpそうです。 – ydoow

+0

あなたのアプローチも間違っていたので、問題が 'from clause'にないので、私は投票しました。私は投票を削除するが、それについて考える。 – danihp

-1
SELECT  `object_id`, `object_name`, 
       case 
        when rental_state = 'Open' then `person_name` 
        when r1.rental_rental_id is null then null 
       else `rental_state` 
       end as RentedTo 
FROM   `object` 
LEFT JOIN `rental2object` r1 ON `object_id` = r1.`object_object_id` 
LEFT JOIN `rental`     ON `rental_id` = r1.`rental_rental_id` 
LEFT JOIN `person`     ON `person_id` = `person_person_id` 
where   r1.rental_rental_id = 
       (select max(r2.`rental_rental_id`) 
        from `rental2object` r2 
        where r2.`object_object_id` = r1.`object_object_id` 
        group by r2.`object_object_id`) 
       or r1.rental_rental_id is null 
GROUP BY `object_id`; 
関連する問題