2013-03-11 4 views
1

에서에서 조인 행에 조건 : 지금은 foreign_idordersactivities에 가입해야MySQL은 - 나는 두 개의 테이블이 바로 테이블

mysql> select * from orders; 
+------+---------------------+------------+---------+ 
| id | created_at   | foreign_id | data | 
+------+---------------------+------------+---------+ 
| 1 | 2010-10-10 10:10:10 |   3 | order 1 | 
| 4 | 2010-10-10 00:00:00 |   6 | order 4 | 
| 5 | 2010-10-10 00:00:00 |   7 | order 5 | 
+------+---------------------+------------+---------+ 

mysql> select * from activities; 
+------+---------------------+------------+------+ 
| id | created_at   | foreign_id | verb | 
+------+---------------------+------------+------+ 
| 1 | 2010-10-10 10:10:10 |   3 | get | 
| 2 | 2010-10-10 10:10:15 |   3 | set | 
| 3 | 2010-10-10 10:10:20 |   3 | put | 
| 4 | 2010-10-10 00:00:00 |   6 | get | 
| 5 | 2010-10-11 00:00:00 |   6 | set | 
| 6 | 2010-10-12 00:00:00 |   6 | put | 
+------+---------------------+------------+------+ 

을 : 모든 주문 등을 위해 (있는 경우) 하나의 작업을 선택 ABS(TIMESTAMPDIFF(SECOND, orders.created_at, activities.created_at))은 최소입니다. 예 : 순서와 활동은 거의 동시에 생성되었습니다.

+----------+---------+---------------------+-------------+------+---------------------+ 
| order_id | data | order_created_at | activity_id | verb | activity_created_at | 
+----------+---------+---------------------+-------------+------+---------------------+ 
|  1 | order 1 | 2010-10-10 10:10:10 |   1 | get | 2010-10-10 10:10:10 | 
|  4 | order 4 | 2010-10-10 00:00:00 |   4 | get | 2010-10-10 00:00:00 | 
|  5 | order 5 | 2010-10-10 00:00:00 |  NULL | NULL | NULL    | 
+----------+---------+---------------------+-------------+------+---------------------+ 

다음 쿼리는 원하는 행을 포함하는 행 집합을 생성합니다. GROUP BY 문이 포함 된 경우 activities의 행을 제어 할 수 없습니다.

SELECT o.id AS order_id 
    , o.data AS data 
    , o.created_at AS order_created_at 
    , a.id AS activity_id 
    , a.verb AS verb 
    , a.created_at AS activity_created_at 
FROM orders AS o 
LEFT JOIN activities AS a ON a.foreign_id = o.foreign_id; 

이러한 쿼리를 작성할 수 있습니까? 이상적으로 나는이 섹션이 더 큰보고 질투의 일부이기 때문에 group by을 사용하지 않는 것이 좋습니다. 당신이 원하는 무엇을

+0

이 줄은 : ABS (TIMESTAMPDIFF (SECOND, orders.created_at, activities.created_at))'? –

+0

이 값을 최소화하고 싶습니다. 예 : 주문이 11:00에 생성되고 3 개의 활동 (1, 09:00), (2, 10:00), (3,11:00), (3, 12:00)이있는 경우, 세 번째 활동. 그 줄은 창조 또는 주문과 활동 사이의 초를 반환합니다. –

답변

1

두 테이블이 어떤 신비 외래 키를 참조하기 때문에이 아래 쿼리 오류 가능성,하지만 그것은 당신에게 당신이 당신의 목적을 위해 적용 할 수있는 원리를 제공 할 수 있습니다 ...

DROP TABLE IF EXISTS orders; 

CREATE TABLE orders 
(id INT NOT NULL PRIMARY KEY 
,created_at DATETIME NOT NULL 
,foreign_id INT NOT NULL 
,data VARCHAR(20) NOT NULL 
); 

INSERT INTO orders VALUES 
(1 ,'2010-10-10 10:10:10',3 ,'order 1'), 
(4 ,'2010-10-10 00:00:00',6 ,'order 4'), 
(5 ,'2010-10-10 00:00:00',7 ,'order 5'); 

DROP TABLE IF EXISTS activities; 

CREATE TABLE activities 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY 
,created_at   DATETIME NOT NULL 
,foreign_id INT NOT NULL 
,verb VARCHAR(20) NOT NULL 
); 

INSERT INTO activities VALUES 
(1,'2010-10-10 10:10:10',3,'get'), 
(2,'2010-10-10 10:10:15',3,'set'), 
(3,'2010-10-10 10:10:20',3,'put'), 
(4,'2010-10-10 00:00:00',6,'get'), 
(5,'2010-10-11 00:00:00',6,'set'), 
(6,'2010-10-12 00:00:00',6,'put'); 

SELECT o.id order_id 
    , o.data 
    , o.created_at order_created_at  
    , a.id activity_id 
    , a.verb 
    , a.created_at activity_created_at 
    FROM activities a 
    JOIN orders o 
    ON o.foreign_id = a.foreign_id 
    JOIN 
    (SELECT a.foreign_id 
      , MIN(ABS(TIMEDIFF(a.created_at,o.created_at))) x 
     FROM activities a 
     JOIN orders o 
      ON o.foreign_id = a.foreign_id 
     GROUP 
      BY a.foreign_id 
    ) m 
    ON m.foreign_id = a.foreign_id 
    AND m.x = ABS(TIMEDIFF(a.created_at,o.created_at)) 
UNION DISTINCT 
SELECT o.id 
    , o.data 
    , o.created_at 
    , a.id 
    , a.verb 
    , a.created_at 
    FROM orders o 
    LEFT 
    JOIN activities a 
    ON a.foreign_id = o.foreign_id 
WHERE a.foreign_id IS NULL; 
; 

+----------+---------+---------------------+-------------+------+---------------------+ 
| order_id | data | order_created_at | activity_id | verb | activity_created_at | 
+----------+---------+---------------------+-------------+------+---------------------+ 
|  1 | order 1 | 2010-10-10 10:10:10 |   1 | get | 2010-10-10 10:10:10 | 
|  4 | order 4 | 2010-10-10 00:00:00 |   4 | get | 2010-10-10 00:00:00 | 
|  5 | order 5 | 2010-10-10 00:00:00 |  NULL | NULL | NULL    | 
+----------+---------+---------------------+-------------+------+---------------------+ 
+0

감사합니다. 이것은 매우 도움이되었습니다. 내가 쿼리 조금 수정 결국 : o.id SELECT, o.data, a.verb, 좌 가입 \t 오 수주 MX '( \t \t SELECT o2.id이 o_id \t \t, a2.id A_ID \t \t, MIN (ABS (TIMESTAMPDIFF (SECOND, a2.created_at, o2.created_at가))) 주문 \t \t 활동이 o2.foreign_id = a2.foreign_id \tON \t \t \t을 A2 가입이 상판 \t \t을 X m.o_id = o.id ON o2.foreign_id \t) m \t \t BYGROUP \t \t \t \t 좌, 활동을 m.a_id = a.id' –

+0

옵스의 ON \t \t 가입 나는하지 않았다 편집을 확인하십시오. 내 수정 된 쿼리는 동일한 결과를 얻는 것으로 보이며 사용자의 쿼리보다 다소 간단합니다. –

+0

o2.foreign_id = a2.foreign을 감안할 때 a2.id를 선택해야 할 부분이 없습니다. 나는 우리의 쿼리가 논리적으로 동일하다고 생각하지 않기 때문에 더 큰 데이터 세트에서 다른 결과를 산출 할 것입니다. 그러나 당신 만이 옳은 것을 말할 수 있습니다. 또한, 둘 다 큰 시간 차이로 고투 할 것입니다. 초로 변환하고, 수학을 수행 한 다음 변환하는 것이 더 나을 수도 있습니다. 실적면에서 볼 때 내 것보다 실제로 귀하의 것이 더 빠르다는 부적절한 의혹이 있습니다. 그러나 확실하지 않습니다. – Strawberry

관련 문제