将带有2个JOINS和COUNT的SELECT转换为UPDATE语句

时间:2013-10-03 00:21:27

标签: sql tsql

我疯狂地试图弄清楚如何正确地写这个,我在这里扔冰雹玛丽。我已经近距离搜索了,但还没找到能让我“点击”的东西。

情况如下:有3个表(parens中涉及的列):

  • prods(prod_id PK,prod_grp_id)
  • prod_grps(prod_grp_id PK,prod_grp_mgr_nm)
  • prod_grp_prods(prod_id,prod_grp_id)

产品可以属于多个prod_grp。例如,棒球可以在体育prod_grp中,其可以具有prod_grp_mgr_nm =“AssMGR_Bill”,同时也在具有prod_grp_mgr_nm =“LeadMGR_Jake”的general_merch组中。我需要遍历prods表中的每个项目并更新每个项目的“prod_grp_id”值,以便它包含由prod_grp_mgr_nm中具有“LeadMGR”的人管理的prod_group_id。我想只在prod_grp_mgr_nm包含“LeadMGR”的prod_grp中更新prods。这里的目标是将每个产品与由主管经理管理的组相关联(如果存在一个(且只有一个)。

到目前为止,我已经有了这个SELECT语句:

    SELECT prods.prod_id
    FROM prods p
    INNER JOIN prod_grp_prods pgp
    ON prod.prod_id = pgp.prod_id
    INNER JOIN prod_grps pg
    ON pgp.prod_grp_id = pg.acct_grp_id
    WHERE pg.prod_grp_mgr_nm LIKE '%LeadMGR%'
    GROUP BY p.prod_id HAVING COUNT(p.prod_id) = 1
    ORDER BY p.prod_id`

这将返回所有需要更新的prod_ids。

3 个答案:

答案 0 :(得分:0)

此查询将解决您的基本问题。

alter table prods
drop column prod_grp_id

正如您所描述的,产品和组之间存在多对多的关系。您还有表prod_grp_prods来实现该关系。在产品表中使用组ID字段非常简单,这是一个坏主意。

编辑从此处开始

这是一个绑定解决方案

update p
set prod_grp_id = pgp.prod_grp_id
from prods p join prod_grp_prods pgp on p.prod_id = pgp.prod_id
join (
select prod_id, count(*) records
from prod_grp_prods 
group by prod_id
having count(*) = 1) temp on temp.prod_id = p.prod_id

您需要另一个查询来取消其他记录。

答案 1 :(得分:0)

 UPDATE prods
 SET    prod_grp_id = BS.prod_grp_id
 FROM   (
          SELECT prods.prod_id,
                 pgp.prod_grp_id

          FROM   prods p 

                 INNER JOIN prod_grp_prods pgp ON 
                 prod.prod_id = pgp.prod_id 

                 INNER JOIN prod_grps pg ON 
                 pgp.prod_grp_id = pg.acct_grp_id 

          WHERE  pg.prod_grp_mgr_nm LIKE '%LeadMGR%' 

          GROUP BY 
                 p.prod_id,
                 pgp.prod_grp_id 

          HAVING COUNT(p.prod_id) = 1 
     ) BS

  WHERE prods.prod_id = BS.prod_id

答案 2 :(得分:0)

我尝试使用以下查询复制您的问题。我使用子查询来更新prods表。我希望这会复制你的问题。

create table #prods (prod_id int PRIMARY KEY, prod_grp_id int)
create table #prod_grps (acct_grp_id int PRIMARY KEY, prod_grp_mgr_nm varchar(200))
create table #prod_grp_prods (prod_id int , prod_grp_id int)

-- insert testing data
insert into #prods values (1, null), (2,null), (3, null)
insert into #prod_grps values (999, 'AssMGR_Bill'), (998, 'LeadMGR_Jake'), (995, 'LeadMGR_Jake')
insert into #prod_grp_prods values (1, 999), (2, 995), (3, 999), (1,998)

-- original query
SELECT p.prod_id, pgp.prod_grp_id
    FROM #prods p
    INNER JOIN #prod_grp_prods pgp
    ON p.prod_id = pgp.prod_id
    INNER JOIN #prod_grps pg
    ON pgp.prod_grp_id = pg.acct_grp_id
    WHERE pg.prod_grp_mgr_nm LIKE '%LeadMGR%'
    GROUP BY p.prod_id , pgp.prod_grp_id
    HAVING COUNT(p.prod_id) = 1
    ORDER BY p.prod_id

-- update query
update #prods set prod_grp_id = t.prod_grp_id
from 
(
  SELECT p.prod_id, pgp.prod_grp_id
    FROM #prods p
    INNER JOIN #prod_grp_prods pgp
    ON p.prod_id = pgp.prod_id
    INNER JOIN #prod_grps pg
    ON pgp.prod_grp_id = pg.acct_grp_id
    WHERE pg.prod_grp_mgr_nm LIKE '%LeadMGR%'
    GROUP BY p.prod_id , pgp.prod_grp_id
    HAVING COUNT(p.prod_id) = 1

)t  
where t.prod_id = #prods.prod_id

-- view results
select * from #prods