【问题标题】:Couldn't update one table from the values of three tables (merging three into one)无法从三个表的值更新一个表(将三个合并为一个)
【发布时间】:2015-12-11 18:53:41
【问题描述】:

我在mysql数据库中有下表

create table tbl_1(pid int, loc varchar(100), avaId int,xpId int,qf varchar(100));
create table tbl_2(soid int,pid int,sid int,name2 varchar(100), nrt2 int);
create table tbl_3(woid int,pid int,wid int,name3 varchar(100), nrt3 int);

create table tbl_sourcef(id int primary key auto_increment,pid int, loc varchar(100), avaId int,xpId int,qf varchar(100),sid int,nrt2 int,wid int,nrt3 int);

将数据插入上述表格后

insert into tbl_1 values (1000,'Bangalore',30,9,'ABC');

insert into tbl_2 values(0,1000,1,'name1',8);
insert into tbl_2 values(1,1000,8,'name2',5);
insert into tbl_2 values(2,1000,7,'name3',6);

insert into tbl_3 values(0,1000,2,'D1',9);
insert into tbl_3 values(1,1000,1,'D2',2);
insert into tbl_3 values(2,1000,3,'D3',0);
insert into tbl_3 values(3,1000,4,'D4',5);

下面是上面 tbl_1,tbl_2,tbl_3 中的行

我正在尝试像这样将这三个表合并到一个表中 -

这对一组 pid 正常工作。当我使用另一组 pid 时,它会失败,子查询返回超过 1 行。我找不到导致问题的原因

我正在使用一个名为 fupdate() 的存储过程

这是SP的定义:

CREATE PROCEDURE fupdate(
pid int,loc varchar(100),avaId int,xpId int,qf varchar(100)
)
begin
        declare pi int Default 1;
        WHILE pi  <= 10 DO
            insert into tbl_sourcef(pid,loc,avaId,xpId,qf)values(pid,loc,avaId,xpId,qf);
            SET  pi = pi + 1;
        END WHILE;

     begin
              declare i int Default 1 ;
              declare si int default 0;
              declare es int;
              set es=(select count(sid) from tbl_2 where pid=pid);
                WHILE i  <= es DO
                    update tbl_sourcef ff
                    set ff.sid=(select sid from tbl_2 where soid=si and pid=pid),
                        ff.nrt2=(select nrt2 from tbl_2 where soid=si and pid=pid)
                    where id=i and pid=pid;
                    SET  i = i + 1;
                    SET si=si+1;
                END WHILE;
      end;
      begin
              declare wi int Default 1 ;
              declare wii int default 0;
              declare ew int;
              set ew=(select count(wid) from tbl_3 where pid=pid);
                WHILE wi  <= ew DO
                    update tbl_sourcef ff
                    set ff.wid=(select wid from tbl_3 where woid=wii and pid=pid ),
                        ff.nrt3=(select nrt3 from tbl_3 where woid=wii and pid=pid)
                    where id=wi and pid=pid ;
                    SET  wi = wi + 1;
                    SET wii=wii+1;
                END WHILE;
        end;

end

这就是我如何称呼我的 SP -

call fupdate(1000,'Bangalore',30,9,'ABC')

有没有更好的方法来达到我期望的结果?

仅供参考,tbl_3 最多有 5 行,tbl_2 最多可以包含 3 行相同的 pid。因此,我想为每个 pid 显示单个表中 5 行内的三个表中的所有字段。我该怎么做?

【问题讨论】:

  • 您需要从 3 个表中选择记录?为什么您尝试使用 JOIN 创建过程而不是简单的 SELECT?
  • 因为我有相同的 id(pid),我不能简单地加入...如果我这样做,我会从表 2 和表 3 中获得冗余行
  • 您永远不应该逐行更新。这只是一种糟糕的编码习惯。这需要基于集合以及使用连接。如果你得到多个具有不同值的行,你需要有业务规则来确定哪个值是正确的。
  • 非常感谢,我从连接开始,意识到我无法满足这个要求。还有其他方法可以达到预期的结果吗?

标签: mysql sql tsql


【解决方案1】:

只需用以下 SQL 替换所有代码

 select *
 from tbl_1 t1 left join 
 (select ISNULL(t2.pid, t3.pid) as merge_pid, t2.sid, t2.nrt2, t3.wid, t3.nrt3
   from tbl_2 t2 full join tbl_3 t3 on t2.soid = t3.woid) as mrg_table
 on t1.pid = mrg_table.merge_pid

编辑以根据聊天中指定的要求提供以下新方法:

“我正在寻找的是:每个 pid 有 5 条记录 tbl_sourcef,应该包含 table1(行可以是多余的 单个 pid),表 2 和表 3(来自 tbl_2 和 tbl_3 的行不应该 重复)在 tbl_sourcef 表中”

 select pid, loc, avaId, xpId, qf, sid, nrt2, wid, nrt3 
 from tbl_1,
 (select ZZZ.M_ID, t2.*, t3.* from
     (select 1 as M_ID union select 2 union select 3 union select 4 union select 5) ZZZ
 left join 
 (select ROW_NUMBER() OVER (ORDER by soid) ID1, pid as pid1, sid, nrt2 from tbl_2 ) t2
 on zzz.M_ID = t2.ID1 
 left join 
 (select ROW_NUMBER() OVER (ORDER by woid) ID2, pid as pid2, wid, nrt3 from tbl_3 ) t3
 on zzz.M_ID = t3.ID2) YYY
 where tbl_1.pid = ISNULL(YYY.pid1, YYY.pid2)

【讨论】:

  • 嗨,Douglas,谢谢您。但我收到错误 ' [Err] 1582 - 调用本机函数 'ISNULL'' 中的参数计数不正确 .. 正在检查它
  • 由于一个简单的查询提供了所需的数据,是否可以只创建一个视图(CREATE VIEW view_1 as select....)并完全放弃使用存储过程?
  • 完全加入tbl_3,你的意思是t2.pid=t3.pid ??请注意,“pid”是这三个表的唯一参考。 soid 和 woid 不能作为相等条件
  • 但您的评论与您期望的结果表不匹配。为什么 tbl_sourcef 的第一行应该有 sid=1 和 wid=2?导致它们连接的那两行有什么特别之处?为什么只加入那 2 行?如果您在 pid 上加入,那么所有行都会相互加入。
  • 对不起,如果有什么混淆了..如果你查看 SP,我使用 pid 作为条件而不是 soid 和 woid.. pid 是所有三个表中唯一相同的 id
猜你喜欢
  • 1970-01-01
  • 2020-11-26
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2013-03-19
相关资源
最近更新 更多