2013-10-13 2 views
0

좋아, 세부 사항을 추상화하여 내 질문을 단순화하려고했지만 명확하지 않았으며 사회자 요구 사항을 충족하지 못했습니다. 그래서 나는 내 문제가있는 전체 질의를 더 자세하게 게시 할 것이며 실제로 고민하고있는 질의를 게시 할 것이다. 질문이 여전히 부적절한 경우 불확실한 점에 대해 구체적으로 설명해 주시겠습니까? 명확히하기 위해 최선을 다할 것입니다.MySQL의 기준에 따라 하나의 행에 왼쪽으로 조인

첫째, 여기에 각 침대에 대한 모든 할당 행을 반환 현재 쿼리입니다 :

SELECT 
    beds.bed_id, 
    beds.bedstatus, 
    beds.position as bed_position, 
    rooms.room_id, 
    rooms.room, 
    wings.wing_id, 
    wings.name as wing_name, 
    buildings.building_id, 
    buildings.name as building_name, 
    assignments.assignment_id, 
    assignments.student_id, 
    assignments.assign_dt, 
    assignments.assigned_by, 
    assignments.assignment_status, 
    assignments.expected_arrival_dt as arrival_dt, 
    assignments.room_charge_type, 
    students.first_name, 
    students.last_name, 
    meal_plans.name as meal_plan_name, 
    room_rates.rate_name 
FROM 
    beds 
LEFT JOIN 
    rooms ON (beds.room_id = rooms.room_id) 
LEFT JOIN 
    wings ON (rooms.wing_id = wings.wing_id) 
LEFT JOIN 
    buildings ON (wings.building_id = buildings.buildings_id) 
LEFT JOIN assignments ON 
    ((beds.bed_id=assignments.bed_id) AND (term_id = @term_id)) 
LEFT JOIN 
    students ON (assignments.student_id = students.student_id) 
LEFT JOIN 
    meal_plans ON (assignments.meal_plan_id = meal_plans.meal_plan_id) 
LEFT JOIN 
    room_rates ON (room_rate_id = room_rates.room_rate_id) 
WHERE 
    (
    (rooms.room IS NOT NULL) AND 
    (rooms.assignable = 1) AND 
    (buildings.active = 1) AND 
    (buildings.building_id = @building_id) 
) 
ORDER BY BY rooms.room; 

문제는 "assignment_status에 의해 구별 각 방은"할당 "테이블에 여러 행이있을 수 있다는 것이다 "필드와 각 과제마다 하나의 행이 필요합니다. assign_status의 값에 따라 어떤 할당 행을 선택할 지 결정하고 싶습니다. 즉, 할당 상태가 "활성"상태라면 그 행을 원합니다. 그렇지 않으면 "승인 대기 중"상태 인 행이 있으면 그 행 등을 원합니다.

Barmar의 제안은

LEFT JOIN (SELECT * 
     FROM OtherTable 
     WHERE <criteria> 
     ORDER BY CASE status 
        WHEN 'Active' THEN 1 
        WHEN 'Waiting Approval' THEN 2 
        WHEN 'Canceled' THEN 3 
        ... 
       END 
     LIMIT 1) other 

이 매우 도움이되었다 나는이 방법을 시도 :

SELECT 
    beds.bed_id, 
    beds.bedstatus, 
    beds.position as bed_position, 
    rooms.room_id, 
    rooms.room, 
    wings.wing_id, 
    wings.name as wing_name, 
    buildings.building_id, 
    buildings.name as building_name, 
    assign.assignment_id, 
    assign.student_id, 
    assign.assign_dt, 
    assign.assigned_by, 
    assign.assignment_status, 
    assign.expected_arrival_dt as arrival_dt, 
    assign.room_charge_type, 
    students.first_name, 
    students.last_name, 
    meal_plans.name as meal_plan_name, 
    room_rates.rate_name 
FROM 
    beds 
LEFT JOIN 
    rooms ON (beds.room_id = rooms.room_id) 
LEFT JOIN 
    wings ON (rooms.wing_id = wings.wing_id) 
LEFT JOIN 
    buildings ON (wings.building_id = buildings.buildings_id) 

LEFT JOIN (SELECT * 
      FROM assignments 
      WHERE ((assignments.bed_id==beds.bed_id) AND (term_id = @term_id)) 
      ORDER BY CASE assignment_status 
         WHEN 'Active' THEN 1 
         WHEN 'Waiting Approval' THEN 2 
         WHEN 'Canceled' THEN 3 
        END 
      LIMIT 1) assign 

LEFT JOIN 
    students ON (assign.student_id = students.student_id) 
LEFT JOIN 
    meal_plans ON (assign.meal_plan_id = meal_plans.meal_plan_id) 
LEFT JOIN 
    room_rates ON (room_rate_id = room_rates.room_rate_id) 
WHERE 
    (
    (rooms.room IS NOT NULL) AND 
    (rooms.assignable = 1) AND 
    (buildings.active = 1) AND 
    (buildings.building_id = @building_id) 
) 
ORDER BY rooms.room; 

을하지만 문제는 여기 OtherTable (과제)는 FK에 따라 부모 쿼리에 가입되어 있다는 것입니다 실현 :

((beds.bed_id=assignments.bed_id) AND (term_id = @term_id)) 

beds.bed_id가 subselect의 범위에 있지 않기 때문에 subselect를 수행 할 수 없습니다. Barmar의 의견에 따르면 조인 기준은 subselect 외부에 있어야합니다. 그러나 결과를 방 당 하나의 행으로 제한하고 subselect 외부로 조인을 이동하는 방법을 파악하는 데 문제가 있습니다. GROUP BY를 사용하려는 여행 동호인의 제안이 더 유익 할 지 모르지만 그룹화 방법을 결정할 수 없었는지 궁금합니다.

내가 추가 설명을 할 수 있는지 알려주세요.

원래 질문 :

내가 왼쪽으로 할 표 A에서 필요로하는 다른 테이블의 단일 행에 가입, 표 B 회의 일정 기준 (복수가있을 수 있습니다 또는 기준을 충족 표 B에 행) . 여러 행이있는 경우 테이블 B의 필드 값을 기반으로 조인 할 B 행을 선택하려고합니다. 예를 들어 상태 열 = '활성'인 B 행이 있으면 그 행을 원합니다 if not = 'Waiting Approval'상태의 행이 있다면 status = 'Canceled'인 행이 있으면 해당 행을 원합니다. 행 등을 원합니다. 하위 선택없이 수행 할 수 있습니까? 하위 선택?

+0

왜 아래로 투표합니까? – scotru

+0

기준은 설계시에 완전히 정의되어 있습니까? 당신의'etc.'은 그것을 불확실하게합니까? –

+0

예, 디자인 타임에 완전히 알려져 있음 (더 긴 목록이지만 디자인 타임에는 모두 알려져 있음) – scotru

답변

1

(그러나 모든 경우에) 당신이 하위 선택하지 않고 그것을 할 수 있습니다. 테이블 A의 고유 필드 인 일반적으로 ID 인 GROUP BY이 필요합니다. 이렇게하면 표 B에서 하나의 행만 확보됩니다. 그러나 원하는 행을 선택하는 것은 까다로운 부분입니다. MAX()와 같은 집계 함수가 필요합니다. B의 필드가 숫자이면 쉽게 할 수 있습니다. 그렇지 않은 경우 B의 필드에 일부 SQL 함수를 적용하여 정렬 할 점수와 같은 것을 계산할 수 있습니다. 예를 들어, ActiveCancelled 등보다 높은 값에 해당 할 수 있습니다. 하위 선택없이 작동하고 큰 데이터 세트에서 더 빠를 가능성이 높습니다.

하위 선택으로 쉽게 할 수 있습니다.Barmar의 솔루션을 사용할 수도 있고, B의 한 특정 필드 만 필요하면 하위 쿼리를 외부 쿼리의 SELECT 절에 넣을 수도 있습니다.

+0

아마도 Barmar가 제안한 것과 같은 CASE 함수에서 MAX 함수를 사용할 수 있습니다 (내 상태 필드가 숫자가 아니기 때문에)? – scotru

4

사용 : 어떤 경우에는

LEFT JOIN (SELECT * 
      FROM OtherTable 
      WHERE <criteria> 
      ORDER BY CASE status 
         WHEN 'Active' THEN 1 
         WHEN 'Waiting Approval' THEN 2 
         WHEN 'Canceled' THEN 3 
         ... 
        END 
      LIMIT 1) other 
+0

이것을 구현하려고합니다. 내 기준에는 부모 테이블의 pk에 대한 참여가 포함될 수 있습니까? OtherTable.fk = A.pk? – scotru

+0

조인 조건이 subselect 외부에 있어야한다고 생각합니다. 원하는 것을 수행하려면 subselect에서 모든 행을 리턴하고 조인 한 후 원하는 상태로 행을 필터링해야합니다. 나는 지금 그 질문을 쓰려고 노력할 시간이 없다. – Barmar

0

이것이 내 목표를 달성하는지 확인하기 위해 추가 테스트가 필요합니다.하지만 나는 바 보이의 사례 논리와 결합 된 쿼리로 그룹에 대한 travelboy의 제안을 사용했습니다. 대답). 검색어는 다음과 같습니다.

SELECT 
    beds.bed_id, 
    beds.bedstatus, 
    beds.position as bed_position, 
    rooms.room_id, 
    rooms.room, 
    wings.wing_id, 
    wings.name as wing_name, 
    buildings.building_id, 
    buildings.name as building_name, 
    assignments.assignment_id, 
    assignments.student_id, 
    assignments.assign_dt, 
    assignments.assigned_by, 
    assignments.assignment_status, 
    assignments.expected_arrival_dt as arrival_dt, 
    assignments.room_charge_type, 
    MIN(CASE assignments.assignment_status 
     WHEN 'Active' THEN 1 
     WHEN 'Waiting Approval' THEN 2 
     WHEN 'Canceled' THEN 3 
     END), 
    students.first_name, 
    students.last_name, 
    meal_plans.name as meal_plan_name, 
    room_rates.rate_name 
FROM 
    beds 
LEFT JOIN 
    rooms ON (beds.room_id = rooms.room_id) 
LEFT JOIN 
    wings ON (rooms.wing_id = wings.wing_id) 
LEFT JOIN 
    buildings ON (wings.building_id = buildings.building_id) 

LEFT JOIN assignments 
    ON ((assignments.bed_id=beds.bed_id) AND (term_id = 28)) 
LEFT JOIN 
    students ON (assignments.student_id = students.student_id) 
LEFT JOIN 
    meal_plans ON (assignments.meal_plan_id = meal_plans.meal_plan_id) 
LEFT JOIN 
    room_rates ON (assignments.room_rate_id = room_rates.room_rate_id) 
WHERE 
    (
    (rooms.room IS NOT NULL) AND 
    (rooms.assignable = 1) AND 
    (buildings.active = 1) 
) 
GROUP BY 
    bed_id 
ORDER BY rooms.room; 
+0

이렇게하면 제대로 작동하지 않게되어 잘못된 행이 표시됩니다. 자세한 내용은 http://stackoverflow.com/questions/20822574/sql-get-entire-row-based-on-minimum-value-of-calculated-column/20822776?noredirect=1#20822776을 참조하십시오. – scotru

관련 문제