2011-02-16 2 views
1

휴우, 제목은 한 마디입니다. 다시 한 번 나는이 질문을하는 법을 정확히 알지 못해서 제가 예제를 사용할 것입니다. 아이템이있는 게임을 만들고 있다고 가정 해 봅시다. 아이템에는 효과, 보너스 및 요구 사항이 있습니다.여러 자식 테이블의 다중 연관 행이 필요한 여러 행을 선택하기위한 최상의 mysql 쿼리

따라서 items 테이블의 각 레코드에는 effects 테이블, bonuses 테이블 및 requirements 테이블에 여러 하위 레코드가 있습니다.

그리고 게임에 표시 할 모든 효과, 보너스 및 요구 사항을 포함하여 100 개의 가장 최근 항목을 선택하고 싶습니다.

이 작업을 수행하는 가장 최적화 된 방법은 무엇입니까? 하나의 쿼리로 수행 할 수 있습니까? 그리고 그것은 심지어 실용적입니까? 감사.

+0

왜 JOINS를 사용하지 않으시겠습니까? 테이블이 너무 큽니까? 'SELECT * FROM items JOIN이 아이템에 영향을줍니다 .ID 아이템에 대한 JOIN 보너스 .ID 항목에 대한 JOIN 요구 사항.ID ORDER BY items.date DESC LIMIT 100' – criticus

+0

항목별로 여러 가지 효과, 보너스 및 필수 항목이 필요합니다. 내 이해는 모든 항목에 대해 1 효과, 1 보너스 및 1 요청을 반환합니다. 나는 틀린가? – Ryan

+0

모든 효과, 보너스, 선택한 항목에 대한 요구 사항을 반환합니다. 그리고 효과, 보너스 또는 요구 사항이없는 항목이 있다면 LEFT JOIN – criticus

답변

1

하나의 쿼리에서 달성 될 수 있지만 꽤 클 것이고 두 배가 될 것입니다. 하나의 쿼리에서 이와 같은 작업을 수행하는 가장 이상적인 유일한 시간은 "하나의 관계 있음"관계가있는 경우입니다. 즉, 항목은 간단한 참여로 수행 할 수있는 하나의 효과를 가지며 항목은 하나의 프로그램 만 반환합니다.

간단한 사례를 들려주세요. 당신은 2 개의 항목을 가지고 있으며 각각은 많은 관계를 가진 3 개의 효과를 가지고 있습니다.

SELECT item.*, effect.* 
FROM item 
JOIN item_effect ON item.id = item_effect.item_id 
JOIN effect ON effect.id = item_effect.effect_id 

반환은있을 수 :

item1 effect1 
item1 effect2 
item1 effect3 
item2 effect2 
item2 effect3 
item2 effect4 

그런 다음 다시 함께 통해 루프 그룹의 모든 항목에있을 것입니다. 요구 사항과 수정 자의 관계로 인해 쿼리는 점점 커지지 만 여전히 공정하게 구성됩니다.

일부 유형의 ORM (Object Relational Mapping)을 사용할 수 있습니다. 그러면 코드를 더 읽기 쉽게 만들 수 있습니다. Kohana의 ORM 구문을 사용합니다.

$items = ORM::factory('item')->find_all(); 
foreach($items as $item) { 
    $effects = $item->effects->find_all(); 
    $bonuses = $item->bonuses->find_all(); 
    $requirements = $item->requirement->find_all(); 
} 

그러나 100 개 항목의 예제에서는 301 개의 검색어를 제안했습니다.

웹 페이지에 이것을 표시하는 경우 페이지 번호 매김 (1-20의 100을 표시)은 해당 숫자를 낮 춥니 다.

사용하는 방법은 상황에 따라 다릅니다. 고려할 사항 :

  • 들이 정말 한 번
  • 100 개 항목을 참조해야합니까 사용됩니다 얼마나 자주
    • 그들이 한 모든 관계를 참조해야합니까 (그 효과를 볼 항목을 클릭 등)
  • +0

    감사합니다. Jacob. foreach 루프를 사용하는 메서드는 실제로 im을 사용하는 솔루션이지만 확실히 분명하므로 내 DB 서버의 킬러입니다. 당신은 제가 생각해야 할 몇 가지 흥미로운 점을 지적했습니다. 불행히도 나는이 데이터를 적어도 한 번은 누군가가 게임을로드 할 때마다 많이 사용합니다. 어떤 유형의 캐싱을 구현할 때가있을 것입니다 ... – Ryan

    +0

    로드에 대한 모든 정보를 알아야 할 필요가 있는지 정말 생각할 것입니다. 어쩌면 그들이 사용하고있는 항목에 대한 정보 만 알 필요가 있을까요? 그렇지 않으면 캐싱이 정말 좋은 생각입니다. (게임을 모른 채 말하기가 어렵다.) – Jacob

    +0

    항목을보고 사용하는 방법 때문에 필요에 따라 추가 항목 데이터를로드해야하는 경우 사용자 경험에 상처를 줄 것이라고 생각합니다. 그러나 나는 확실히 그것을 배제하지 않을 것이다. 나는 그것에 아주 잘 올지 모른다. – Ryan

    -1

    당신은이 같은 수의 할일 뭔가해야 ...

    SELECT `users`.`nickname` , `events`.`nickname` 
    FROM `users` , `events` 
    WHERE `events`.`aid` = `users`.`aid` 
    GROUP BY `events`.`nickname` 
    

    명확히하기 위해, events.aid는 UNIQ입니다 ue 사용자의 ID입니다. 따라서 이러한 모든 레코드를 가져 와서 이벤트별로 그룹화하면 모든 고유 한 이벤트 별명과 해당 항목을 작성한 사용자의 목록이 표시됩니다. enter image description here

    +0

    해당 쿼리는 질문을 해결합니다. 묻는 사람은 특별한 것을 요구하지 않으며, 그는 물건의 모든 관계를 필요로합니다. 또한 조인에 대해서는 http://stackoverflow.com/questions/128965/is-there-something-wrong-with-joins-that-dont-use-the-join-keyword-in-sql-or-mys를 참조하십시오. – Jacob

    관련 문제