2012-07-30 2 views
3

: friends, locations, friend_locationSQL 쿼리 나는 세 개의 테이블이 다 대다 관계

friend_locationfriendslocations 사이의 다 대다 관계를 허용하는 테이블을 조인, 그래서 테이블은 다음과 같이 보일 것이다 :

친구


ID | Name 
1 | Jerry 
2 | Nelson 
3 | Paul 

위치 내가하고 싶은 무엇


ID | Date  | Lat | Lon 
1 | 2012-03-01 | 34.3 | 67.3 
2 | 2011-04-03 | 45.3 | 49.3 
3 | 2012-05-03 | 32.2 | 107.2 

friend_location


Friend_ID | Location_id 
1   | 2 
2   | 1 
3   | 3 
2   | 2 

는 각 친구의 최신 위치를 얻을 수있다.


    select f.id , f.name , last_known_date 
    from friends f, (

    select distinct fl.friend_id as friend_id, fl.location_id as location_id, m.date as last_known_date 
    from friend_location fl 

    inner join (
     select location.id as id, max(date) as date 
     from location 
     group by location.id 
    ) m 

    on fl.location_id=m.id 

    ) as y 
    where f.id=y.friend_id 

어떤 제안을 크게 감상 할 수있다 :

이 내가 여러 사례보고 후 시도한 것입니다,하지만 많은 결과를 반환하지 올바른


ID | Friend | Last Know Location | last know date 
1 | Jerry | 45.3 , 49.3  | 2011-04-03 
2 | Nelson | 34.3 , 67.3  | 2012-03-01 
3 | Paul | 32.2 , 107.2  | 2012-05-03 

결과 .

+0

사용중인 데이터베이스 유형을 나열하십시오.창 함수는 훨씬 간소화되고 간결하게 만들어지기 때문에 응답에 크게 영향을줍니다 (그러나 모든 데이터베이스에서 사용할 수있는 것은 아닙니다). –

+0

마지막으로 알려진 날짜를 별도의 테이블로 이동하는 것이 좋습니다 – cordialgerm

+0

PostgrisSQL 사용. 감사. – Cysneros

답변

1

은 당신이 뭔가를 할 수 있습니다 :

기본적으로
SELECT f.id, f.name, last_known_date, l.Lat, L.Lon 
from Friends f 
join 
(
    select f.id, MAX(l.Date) as last_known_date 
    from Friends f 
    JOIN Friend_Location fl on f.ID = fl.Friend_ID 
    JOIN Location l on l.ID = fl.Location_ID 
    GROUP BY f.id 
) FLMax 
on FLMax.id = f.id 
join Friend_Location fl on fl.friend_ID = f.ID 
join Location l on fl.location_ID = l.ID AND l.Date = FLMax.Last_Known_Date 

문제는 당신이 ID는 고유하기 때문에 당신에게 모든 위치를 줄 것이다 location.id에 의해 그룹화되어 있다는 점이다.

친구가 한 번에 1 위치에만있을 수있는 경우에만 작동합니다.

+0

Friend_Location 테이블에 날짜를 넣어 테이블을 조금 더 정상화 할 수 있습니다. 현재 디자인으로 친구가 같은 위치에 여러 번 체크인하면 여러 위치 기록이 생성됩니다. – Greg

+0

정말 고마워요! 그들은 모두 잘 작동했습니다. 내가 추가 한 유일한 것은 DISTINCT 였는데 각 항목에 대해 하나의 결과 만 얻었는지 확인했습니다. – Cysneros

0

날짜가 위치 테이블에 있기 때문에 데이터 레이아웃이 약간 이상합니다. 그래서, 다음은 각 친구에 대한 최신 날짜 검색 : 위치는하지 않는 것으로 가정

select f.*, maxdate, l.* 
from (select fl.friend_id, max(l.date) as maxdate 
     from friend_location fl 
     JOIN location l 
      on fl.location_id = l.id 
     group by fl.friend_id 
    ) flmax join 
    friends f 
     on flmax.friend_id = f.id 
    join location l 
     on l.date = flmax.maxdate 

이 작동합니다 : 이제

select fl.friend_id, max(l.date) as maxdate 
from friend_location fl 
    location l join 
    on fl.location_id = l.location_id 

을, 그냥이 쿼리에 대한 정보를 다시 가입하자 중복 된 날짜가 있습니다. 그렇다면 쿼리가 좀 더 복잡해집니다. 이 가정을 할 수 있을까요?

0

당신은 사용할 수 있습니다

SELECT 
    a.*, 
    CONCAT(d.Lat, ' , ', d.Lon) AS last_known_location, 
    d.Date AS last_known_date 
FROM 
    friends a 
JOIN 
(
    SELECT a.Friend_ID, MAX(b.Date) AS maxdate 
    FROM  friend_location a 
    JOIN  location b ON a.Location_id = b.ID 
    GROUP BY a.Friend_ID 
) b ON a.ID = b.Friend_ID 
JOIN 
    friend_location c ON b.Friend_ID = c.Friend_ID 
JOIN 
    location d ON c.Location_id = d.ID AND b.maxdate = d.Date 
1

Gregs 쿼리 나에게 올바른 보이는, 내가 유사한 하나 (아래 참조)를 내놓았다. 그러나 현재 db 스키마는 두 친구가 다른 순서로 같은 위치를 방문했을 때 상황을 처리하지 못합니다. 나에게는 날짜 열이 위치가 아닌 friend_location 테이블에 있어야합니다. 그러나 쿼리가 아닌 경우 :

SELECT F.ID, F.Name AS Friend, L.Lat, L.Lon, L.Date 
FROM 
(
    SELECT MAX(L.date) AS max_date, F.ID 
    FROM Friends F 
    JOIN friend_location FL ON F.ID=FL.Friend_ID 
    JOIN Location L ON L.ID=FL.Location_id 
    GROUP BY F.ID 
) AS X 
JOIN Friends F ON X.ID=F.ID 
JOIN friend_location FL ON F.ID=FL.Friend_ID 
JOIN location L ON L.ID=FL.Location_id AND L.Date=X.max_date