mysql左连接只从基表开始的第一行

时间:2014-12-04 13:51:33

标签: mysql sql left-join

我很难想到如何将数据从一个表连接到BASE表......但仅限于基表中的第一行...是否可能?

例如:

TABLE1

item_id  |  insert_datetime  |  value  
---------------------------------------
   2     | 1/1/2014 12:54:05 |   65
   2     | 1/1/2014 12:57:05 |   65
   3     | 8/7/2014 10:01:47 |   87
   3     | 9/8/2014 09:37:21 |   33
   3     | 9/8/2014 09:42:21 |   33
   4     | 2/9/2014 15:22:01 |   58

TABLE2 (按ID分类,日期[不是日期时间],值)

item_id  |   drop_datetime   |  value  
---------------------------------------
   2     | 1/1/2014 00:00:00 |   65
   3     | 9/8/2014 00:00:00 |   33

我需要做这样的事情:

SELECT t1.item_id
, t1.insert_datetime as inserted
, t1.value as ins_value
##
, t2.drop_datetime as cancelled
, t2.value as cld_value
##
FROM table1 t1
##
LEFT JOIN table2 t2
ON t2.item_id = t1.item_id
AND date(t2.drop_datetime) = date(t1.insert_datetime)
AND t1.value = t2.value
##
WHERE 1=1

所以这意味着我需要获取哪些值被取消...但是在 item_id = 2的情况下,存在以下情况:

项目于2014年1月1日12:54:05发货(价值为65)......它被取消了(T2中的第1行),因为参数错误而被重新装载2014年1月1日12:57 :05具有相同的值

我为 item_id = 2获得的是:

item_id  |     inserted      |  ins_value |  cancelled        |   cld_value
-----------------------------------------------------------------------------
   2     | 1/1/2014 12:54:05 |     65     | 1/1/2014 00:00:00 |      65
   2     | 1/1/2014 12:57:05 |     65     | 1/1/2014 00:00:00 |      65

但我需要才能得到这个:

item_id  |     inserted      |  ins_value |  cancelled        |   cld_value
-----------------------------------------------------------------------------
   2     | 1/1/2014 12:54:05 |     65     | 1/1/2014 00:00:00 |      65
   2     | 1/1/2014 12:57:05 |     65     |                   |       

因为实际上,只有第一个被取消..才有可能在MySQL中得到这个结果?

注意: 而且,一个项目也可能会在一小时内被取消两到三次

                                   **EDIT 1**

如果有帮助......所有数据都在SHIP(1)或CANCLED(2)症状的一个表中

消息来源

id  |  item_id  |  insert_datetime  |  value  |  symptom  
-----------------------------------------------------------
1   |     2     | 1/1/2014 12:54:05 |   65    |     1
2   |     2     | 1/1/2014 00:00:00 |   65    |     2
3   |     2     | 1/1/2014 12:57:05 |   65    |     1
4   |     3     | 8/7/2014 10:01:47 |   87    |     1
5   |     3     | 9/8/2014 09:37:21 |   33    |     1
6   |     3     | 9/8/2014 00:00:00 |   33    |     2
7   |     3     | 9/8/2014 09:42:21 |   33    |     1
8   |     4     | 2/9/2014 15:22:01 |   58    |     1

这会有帮助吗?

                                   **POSSIBLE SOLUTION**

看起来这样可行:

SELECT t1.item_id
, t1.insert_datetime as inserted
, t1.value as ins_value
##
, t2.drop_datetime as cancelled
, t2.value as cld_value
##
FROM table1 t1
##
LEFT JOIN table2 t2
ON t2.item_id = t1.item_id
AND date(t2.drop_datetime) = date(t1.insert_datetime)
AND t1.value = t2.value
AND t1.id < t2.id   ## <- this should do the trick
##
WHERE 1=1

2 个答案:

答案 0 :(得分:1)

你可以试试这个:

SQL Fiddle

MySQL 5.5.32架构设置

CREATE TABLE Table1
    (`id` int, `item_id` int, `insert_datetime` datetime, `value` int, `symptom` int)
;

INSERT INTO Table1
    (`id`, `item_id`, `insert_datetime`, `value`, `symptom`)
VALUES
    (1, 2, '2014-01-01 12:54:05', 65, 1),
    (2, 2, '2014-01-01 00:00:00', 65, 2),
    (3, 2, '2014-01-01 12:57:05', 65, 1),
    (4, 3, '2014-07-08 10:01:47', 87, 1),
    (5, 3, '2014-08-09 09:37:21', 33, 1),
    (6, 3, '2014-08-09 00:00:00', 33, 2),
    (7, 3, '2014-08-09 09:42:21', 33, 1),
    (8, 3, '2014-08-09 00:00:00', 33, 2),
    (9, 3, '2014-08-09 09:48:29', 33, 1),
    (10, 3, '2014-09-02 15:22:01', 58, 1)
;

查询1

SELECT DISTINCT t1.item_id
, t1.insert_datetime as inserted
, t1.value as ins_value
, ifnull(t2.insert_datetime,'') as cancelled
, ifnull(t2.value,'') as cld_value
FROM table1 t1
LEFT JOIN table1 t2
ON t2.item_id = t1.item_id
AND date(t2.insert_datetime) = date(t1.insert_datetime)
AND t1.value = t2.value
AND t1.id < t2.id 
AND t2.symptom = 2
WHERE t1.symptom = 1 

<强> Results

| ITEM_ID |            INSERTED | INS_VALUE |           CANCELLED | CLD_VALUE |
|---------|---------------------|-----------|---------------------|-----------|
|       2 | 2014-01-01 12:54:05 |        65 | 2014-01-01 00:00:00 |        65 |
|       2 | 2014-01-01 12:57:05 |        65 |                     |           |
|       3 | 2014-07-08 10:01:47 |        87 |                     |           |
|       3 | 2014-08-09 09:37:21 |        33 | 2014-08-09 00:00:00 |        33 |
|       3 | 2014-08-09 09:42:21 |        33 | 2014-08-09 00:00:00 |        33 |
|       3 | 2014-08-09 09:48:29 |        33 |                     |           |
|       3 | 2014-09-02 15:22:01 |        58 |                     |           |

答案 1 :(得分:0)

你可以试试这个

SET @rowNoIn:=0;
SET @RowNoCn:=0;
SET @itemIn='';
SET @itemCn='';

select i.*,c.*
from(
  SELECT 
    @rowNoIn:=CASE WHEN @itemIn=item_id THEN @rowNoIn+1 ELSE 1 END AS rowNo
    ,@itemIn:=item_id AS item_id
    ,insert_datetime
    ,value
  FROM table1
  ORDER BY item_id, insert_datetime
)i
left join (
  SELECT 
    @rowNoCn:=CASE WHEN @itemCn=item_id THEN @rowNoCn+1 ELSE 1 END AS rowNo
    ,@itemCn:=item_id AS item_id
    ,drop_datetime
    ,value
  FROM table2
  ORDER BY item_id, drop_datetime)c
on 
  i.item_id = c.item_id
  and i.rowNo = c.rowNo

sqlFiddle

注意如果有项目取消,则假定第一项表单table1将被取消(无论在哪个日期),您可以更新代码以更好地满足您的需求,但希望它会带领你走向正确的方向。您应该考虑在table1中添加ID,以便明确引用已取消的记录。