表更新具有相同的值

时间:2013-12-03 15:41:51

标签: mysql database database-design

我正在使用的MYSQL数据库中名为TBL_stay的表旨在通过车牌获取车辆的进出时间。产生以下格式的表:

ID| Plate | Date_in | Time_in | Date_out | Time_out

车辆从另一个表输入数据库,用作缓冲区。 因为正在使用简单的INSERT命令,所以入口日期正好被转移到新表中,没有任何问题。但是退出数据并没有按照我想要的方式更新。

我必须使用更新命令来确保数据不会粘贴到新行上,而不是使用最新的退出数据更新最新的入口数据,我使用的命令会更新每个入口数据条目只有第一个结果。我不确定为什么会这样。你能帮助我吗?

这是退出数据的更新命令:

update tbl_stay 
join tblout_buffer 
on tblout_buffer.plate=tbl_stay.plate 
set tbl_stay.date_out=tblout_buffer.Date_out, tbl_stay.time_out=tblout_buffer.time_out 
where tbl_stay.date_in=tblout_buffer.date_out

缓冲区具有相同的结构:Plate | Date In/out | Time In/out

以下是单个板块的情况示例:

IN缓冲区:

HN51KTG | 2013-12-03 | 06-07-08
HN51KTG | 2013-12-03 | 07-08-09
HN51KTG | 2013-12-03 | 11-25-45

OUT缓冲区:

HN51KTG | 2013-12-03 | 06-34-12
HN51KTG | 2013-12-03 | 10-29-40
HN51KTG | 2013-12-03 | 16-32-14

TBL_STAY:

1 |HN51KTG | 2013-12-03 | 06-07-08 | 2013-12-03 | 06-34-12
2 |HN51KTG | 2013-12-03 | 07-08-09 | 2013-12-03 | 06-34-12
3 |HN51KTG | 2013-12-03 | 11-25-45 | 2013-12-03 | 06-34-12

但我想要实现的是:

1 |HN51KTG | 2013-12-03 | 06-07-08 | 2013-12-03 | 06-34-12
2 |HN51KTG | 2013-12-03 | 07-08-09 | 2013-12-03 | 10-29-40
3 |HN51KTG | 2013-12-03 | 11-25-45 | 2013-12-03 | 16-32-14

更新

Strawberry发布的解决方案是朝着正确方向迈出的一大步,然而,将数据放入表中的过程以及此表上的另一个活动查询会对此解决方案造成一些干扰:

当检测到车牌进入房屋时,车牌,日期&时间加载到tblin_buffer。然后使用insert命令将其插入Plate| Date_in|Time_in|中的tbl_stay列。

通过VB.net GUI每隔几秒运行一次查询,通过查找tbl_stay中具有date_intime_in的条目,生成“现场车辆”表格在date_outtime_out

中没有值

当检测到车牌退出现场时,车牌,日期和时间会加载到tblout_buffer,然后是日期和时间。使用|Date_out|Time_out|命令将时间转移到tbl_stay update列。

每次检测到一个板进入和退出时,插入和更新命令都会触发,理想情况下,它们应该只关注各自表的最新条目。

虽然我接受连接日期和时间可以简化程序,但我最好保持当前列不变,因为这些是所有其他查询和命令中的引用。

下面的一些新代码示例,如果有帮助的话:

原始插入命令:

insert into 
tbl_stay (Plate,Date_in,Time_in) 
select Plate,Date_in,Time_in 
from tblin_buffer 
where not exists 
(select * from tbl_stay where 
(tblin_buffer.Plate=tbl_stay.plate and tblin_buffer.Date_in=tbl_stay.Date_in and tblin_buffer.Time_in=tbl_stay.Time_in))

新的插入命令,改编自Strawberry的解决方案(目前似乎插入缓冲区中的所有行。试图通过上面的“where not exists子句”以及手动指定板值来补偿这一点:

insert into tbl_stay (Plate,date_in,time_in,rank_in)
SELECT   a.plate, a.date_in, a.time_in,rank 
  FROM 
     ( SELECT x.plate, x.date_in, x.time_in, COUNT(*) rank FROM tblin_buffer x 
         JOIN tblin_buffer y 
          ON y.plate = x.plate 
         AND ((y.date_in < x.date_in) OR (y.date_in = x.date_in AND y.time_in <= x.time_in)) 
       GROUP BY x.plate, x.date_in, x.time_in) a 

新的更新命令,也改编自草莓的解决方案:

update tbl_stay
JOIN 
( SELECT x.plate
    , x.date_out
    , x.time_out
    , COUNT(*) rank 
FROM tblout_buffer x 
JOIN tblout_buffer y 
    ON y.plate = x.plate 
    AND ((y.date_out < x.date_out) OR (y.date_out = x.date_out AND y.time_out <= x.time_out)) 
GROUP 
    BY x.plate
    , x.date_out
    , x.time_out
) b
ON b.plate = tbl_stay.plate 
AND b.rank = tbl_stay.rank_in
set tbl_stay.date_out=b.date_out,
tbl_stay.time_out=b.time_out,
tbl_stay.rank_out=b.rank;

1 个答案:

答案 0 :(得分:1)

DROP TABLE IF EXISTS IN_Buffer;

CREATE TABLE IN_Buffer
(plate VARCHAR(12) NOT NULL
,date DATE NOT NULL,time TIME NOT NULL
,PRIMARY KEY(plate,date,time)
);

INSERT INTO IN_Buffer VALUES
('HN51KTG','2013-12-03','06:07:08'),
('HN51KTG','2013-12-03','07:08:09'),
('HN51KTG','2013-12-03','11:25:45');

DROP TABLE IF EXISTS OUT_Buffer;

CREATE TABLE OUT_Buffer
(plate VARCHAR(12) NOT NULL
,date DATE NOT NULL,time TIME NOT NULL
,PRIMARY KEY(plate,date,time)
);

INSERT INTO OUT_Buffer VALUES
('HN51KTG','2013-12-03','06:34:12'),
('HN51KTG','2013-12-03','10:29:40'),
('HN51KTG','2013-12-03','16:32:14');


SELECT a.plate
     , a.date date_in
     , a.time time_in 
     , b.date date_out
     , b.time time_out
  FROM 
     ( SELECT x.plate
            , x.date
            , x.time
            , COUNT(*) rank 
        FROM IN_buffer x 
        JOIN IN_buffer y 
          ON y.plate = x.plate 
         AND ((y.date < x.date) OR (y.date = x.date AND y.time <= x.time)) 
       GROUP 
          BY x.plate
           , x.date
           , x.time
     ) a
  JOIN 
     ( SELECT x.plate
            , x.date
            , x.time
            , COUNT(*) rank 
        FROM OUT_buffer x 
        JOIN OUT_buffer y 
          ON y.plate = x.plate 
         AND ((y.date < x.date) OR (y.date = x.date AND y.time <= x.time)) 
       GROUP 
          BY x.plate
           , x.date
           , x.time
     ) b
    ON b.plate = a.plate 
   AND b.rank = a.rank;

+---------+------------+----------+------------+----------+
| plate   | date_in    | time_in  | date_out   | time_out |
+---------+------------+----------+------------+----------+
| HN51KTG | 2013-12-03 | 06:07:08 | 2013-12-03 | 06:34:12 |
| HN51KTG | 2013-12-03 | 07:08:09 | 2013-12-03 | 10:29:40 |
| HN51KTG | 2013-12-03 | 11:25:45 | 2013-12-03 | 16:32:14 |
+---------+------------+----------+------------+----------+

但是,根据您的评论,实际流程的工作方式如下:

  1. IN_Buffer数据插入stay
  2. 使用OUT_Buffer数据更新stay
  3. 这很容易。只需调整查询,如下所示。请注意,我在stay表中连接了日期和时间......

    CREATE TABLE stay
    (ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    ,Plate VARCHAR(12) NOT NULL
    , dt_in DATETIME NOT NULL
    ,dt_out DATETIME NULL);
    
    INSERT INTO stay (plate,dt_in) 
    SELECT plate,CONCAT(date,' ',time) FROM IN_Buffer;
    
    UPDATE stay m
      JOIN 
         ( 
         SELECT a.plate
         , a.dt_in
         , b.dt_out
      FROM 
         ( SELECT x.plate
                , x.dt_in
                , COUNT(*) rank 
            FROM stay x 
            JOIN stay y 
              ON y.plate = x.plate 
             AND y.dt_in <= x.dt_in 
           GROUP 
              BY x.plate
               , x.dt_in
         ) a
      JOIN 
         ( SELECT x.plate
                , CONCAT(x.date,' ',x.time) dt_out
                , COUNT(*) rank 
            FROM OUT_buffer x 
            JOIN OUT_buffer y 
              ON y.plate = x.plate 
             AND ((y.date < x.date) OR (y.date = x.date AND y.time <= x.time)) 
           GROUP 
              BY x.plate
               , dt_out
         ) b
        ON b.plate = a.plate 
       AND b.rank = a.rank
       ) n
      ON n.plate = m.plate
     AND n.dt_in = m.dt_in
     SET m.dt_out = n.dt_out;