【问题标题】:mysql left join only first row from base tablemysql只从基表中加入第一行
【发布时间】:2023-03-24 04:41:01
【问题描述】:

我正在努力思考如何将数据从一个表 LEFT JOIN 到 BASE 表..但仅适用于基表中的第一行...这甚至可能吗?

例如:

表 1

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 中的第一行)并于 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) 或 CANCEL(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

【问题讨论】:

  • 你怎么知道只有第一个被取消了?我认为数据模型是错误的。 table2 中的 itemid 应该指向一个唯一的 id,这样你就知道哪个被取消了。目前,没有很好的方法来确定这一点,您需要猜测一个业务规则并编写一个不必要的复杂查询来解决该问题。
  • 我不知道这个......我想......但它应该是第二个......实际上,没关系..我需要看看有多少项目被取消和其中有多少不是...但是-详细:(我同意数据模型是错误的,但我没有机会更改它:(
  • 我已经添加了有关原始结构的更多信息......也许会有所帮助

标签: mysql sql left-join


【解决方案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 |                     |           |

【讨论】:

  • 和我的解决方案一样 :) 非常好
【解决方案2】:

你可以试试这个

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 将被取消(无论什么日期),您可以更新代码以更好地满足您的需要,但希望它会导致你进入了正确的方向。您真的应该考虑将 ID 添加到您的 table1 中,这样您就可以明确引用取消的记录。

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 2013-02-05
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 2014-11-12
    相关资源
    最近更新 更多