2016-07-01 1 views
1

지금 렌탈 프로세스를 관리하는 시스템을 개발 중이며 현재 빌려 오는 사람 이름으로 모든 렌털 가능 오브젝트를 효율적으로 쿼리하는 방법이 궁금합니다. 객체가 현재 대여되어있는 경우 그렇지 않으면 해당 열에 NULL이 있어야합니다.mysql 데이터베이스에서 1 : n : 1 : 1 릴레이션에 올바르게 연결하십시오.

내 표는 다음과 같다 :

객체

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

임대

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

사람

rental2object

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

I는 다음과 같이해야 원하는 결과 :

| 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` 

명백한 문제가 그룹화하는 동안 올바른 방법을 모으는 방법을 알지 못합니다.

내 목표를 달성하는 가장 효율적인 방법은 무엇입니까? 당신의 도움을 주셔서 감사합니다.

편집

그 개체 B는 또한 최대 소집에 임대되어 있으므로, 예상 된 결과가 수정되었습니다. 귀하의 질문에 대해

+0

을 시도 person_id로 (다음 인덱스가 암시 적 기본 키입니다) : & rental_state (두 필드와 종합 지수)

  • 사람을 rental_id 'SELECT' 문의 컬럼이 GROUP BY에 존재하지 않습니다. – ydoow

  • +1

    개체 # 2와 # 5는 모두 임대 # 4에 있습니다. 그러나 당신은 당신의 예상 된 결과에 대해 서로 다른 방식으로 처리합니다. 객체 E와 객체 B는 모두 둘 다 동일한 동작이어야합니다. 둘 다 관련이 있습니다. 왜 객체 B가 사람과 관련이있는 Null을 가졌습니까? – danihp

    +0

    좋아, 내가 편집 한 것을보고 내 대답을 확인하고, 왜 그 이유를 모르겠다. – danihp

    답변

    1

    오브젝트 # 2와 # 5는 임대 # 4에 모두 있습니다. 하지만 기대 한 결과에 따라 두 가지 방법으로 처리 할 수 ​​있습니다. 개체 E와 개체 B는 둘 다 동일한 렌탈에 있기 때문에 둘 다 동일한 동작이어야합니다. 그렇지 않다면, 마녀가 제품에 관련자가 있는지 없는지를 판단하는 기준이라고 설명해야합니다.

    에 의해

    그룹은 모든 집계되지 열을 SELECT 절에 포함해야 SQL92 준수하려면 :

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

    이되고 SQL99 준수는 SELECT 절에 모든 집계되지 열을 포함해야 귀하의 경우, functionlly가 아닌 경우 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 이상에서 함수 종속성을 감지하면이 마지막 선택이 유효하지만 가독성을 위해 첫 번째 옵션을 사용하는 것이 좋습니다.

    자세한 내용은 MySQL Handling of GROUP BY을, 자세한 내용은 ONLY_FULL_GROUP_BY을 참조하십시오.

    성능

    당신을위한 인덱스가 있는지 확인 :

    • 객체를 : object_object_id (복합 될 수있다 : OBJECT_ID는 rental2object
    • (다음 인덱스는 암시 적 기본 키입니다) 다른 필드의 인덱스이지만 object_object_id가 인덱스의 첫 번째 필드인지 확인하십시오.
    • renta L는 :
    +0

    다시 쿼리가 원하는 출력과 일치하지 않습니다. –

    +0

    개체 b의 마지막 상태가 반환되지만 OPs solution은 이것이 열려 있고 Max Muster에 임대 된 것으로 예상되는 결과를 기반으로 생각합니다. 쿼리는 객체의 마지막 상태를 찾기 위해 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`;