SQL希望将一个单元格中的值与其他单元格中的值的一部分进行比较

时间:2014-11-13 12:39:18

标签: sql-server

我有

表XXX

ID int
CODE varchar

表格YYY

ID int
X_ID int

导入中的分隔符错误导致一些记录在我的表中两次进入。发生了什么?我不确定。结果就是:表XXX中的两个记录都指的是同一个实体,作为'之前的CODE的一部分;'是一样的。

表XXX

ID   | Code
123  | 456
789  | 456;li

表YYY

ID   | X_ID
111  | 789
222  | 123
333  | 000

现在我需要一个查询来为我需要更新的所有2900条记录执行此操作: 我需要保留YYY中的所有记录。

  

将表YYY中记录111的X_ID更新为123,然后从中删除记录789   表XXX

不需要在1个查询中执行此操作。 那我该怎么办呢?你能帮助我吗? 我写了很多半查询,我觉得自己像一个菜鸟(我在SQL中)

4 个答案:

答案 0 :(得分:1)

这就是我想出的。 事实证明,还有一个表需要更新。 再次感谢MiHaiC的努力。我的答案给了你灵感。

WITH WA AS (
SELECT ID AS BID,
    Code AS BCode 
    FROM XXX
)

SELECT  a.id as 'FOUT_ID', 
    b.Bid as 'GOED_ID', 
    a.code as 'FOUTE_CODE', 
    b.Bcode as 'GOEDE_CODE'
    INTO TEST_QUERY
    from XXX a
    INNER JOIN WA b ON b.BCode = substring (a.code, 1, charindex (';', a.code,0 ) - 1)
    where a.prs_Code like '%;%'

UPDATE YYY
    SET X_ID = TEST_QUERY.GOED_ID
    FROM YYY
        INNER JOIN TEST_QUERY ON TEST_QUERY.FOUT_ID = X_ID
    WHERE ID IN (
        SELECT ID
        FROM ZZZ
            INNER JOIN TEST_QUERY ON TEST_QUERY.FOUT_ID = ZZZ.ID)

UPDATE ZZZ
    SET ID = TEST_QUERY.GOED_ID
    FROM ZZZ
        INNER JOIN TEST_QUERY ON TEST_QUERY.FOUT_ID = D_Melding.mld_prs_ID

希望这可以帮助别人。

答案 1 :(得分:0)

第一次查询:

UPDATE YYY SET X_ID=123 WHERE ID=111

相反,您也可以执行WHERE X_ID=789并获得相同的结果。

第二次查询:

DELETE FROM XXX WHERE ID=789

答案 2 :(得分:0)

对不起,它花了一点时间,我发现的唯一快速解决方案,因为不让你久等不及是使用一个程序:

CREATE OR REPLACE PROCEDURE FIX_XXX_YYY
IS
BEGIN
   --make changes in XXX, to remove delimiter, such that we can get min/max with group by code
   UPDATE XXX
      SET code = SUBSTR (code, 1, INSTR (code, ';') - 1)
    WHERE INSTR (code, ';') > 0;

   COMMIT;

   --update YYY with the correct values by using min/max(id) from XXX, min = first entry so the good one, max =bad entry.
   --basically update all bad entries in YYY with corresponding good value in XXX
   FOR entry IN (  SELECT MIN (id) AS good_id, MAX (id) AS bad_id, code
                     FROM xxx
                 GROUP BY code
                   HAVING COUNT (1) > 1)
   LOOP
      UPDATE yyy
         SET x_id = entry.good_id
       WHERE x_id = entry.bad_id;

      COMMIT;
   END LOOP;

   --delete the duplicates from XXX, i.e the bad entries represented by MAX
   DELETE FROM xxx
         WHERE id IN (SELECT id
                        FROM (SELECT id,
                                     code,
                                     MAX (id) OVER (PARTITION BY code) max_id
                                FROM xxx)
                       WHERE id = max_id);

   COMMIT;

   RETURN;
END FIX_XXX_YYY;

使用以下方法调用它:

BEGIN 
  FIX_XXX_YYY;
  COMMIT; 
END; 

希望这次我做对了。请测试并告诉我。我会删除错误的答案。

答案 3 :(得分:0)

我在之前的回答中犯了一个错误,因为我给出的解决方案是Oracle数据库。 OP需要sqlserver的解决方案。

我已将我的代码翻译成sql:

begin transaction
declare @good_id int
declare @bad_id int
declare @code varchar(128)

--update xxx as to change the lines containing ';' to just the number value. we do this by removing
--every character after ';' including ';'.
--we will use the updated values to calculate min and max over the id column
update XXX set code=SUBSTRING(code,1,CHARINDEX(';',code) - 1) where CHARINDEX(';',code)>0

--declare a cursor to calculate min (the good_id) and max (the bad_id) for a given code in table XXX
--this assumes the wrong id is always inserted secondly, i.e. it's value is always greater than the good id
declare myCursor cursor local fast_forward for
SELECT MIN (id) AS good_id, MAX (id) AS bad_id, code
                     FROM xxx
                 GROUP BY code
                   HAVING COUNT (1) = 2 --this condition is used to filter only duplicate entries, i.e only those entries in XXX that have the same code twice!

open myCursor

while 1=1 --while true
BEGIN
    fetch next from myCursor into @good_id, @bad_id, @code --save the values obtained from the cursor in local variables
    if @@FETCH_STATUS<>0 --when there is nothing left to fetch from the cursor we exit the while loop
    begin
        break
    end

    --update YYY with the correct values by using min/max(id) from the variables @good_id and @bad_id
    update YYY set x_id=@good_id where x_id=@bad_id;        
END --end while loop

close myCursor
deallocate myCursor

--delete the duplicates from XXX, i.e the bad entries represented by MAX
delete from XXX where id in(
select id from (
SELECT id,code,MAX (id) OVER (PARTITION BY code) as max_id FROM xxx) x where id=max_id)

commit transaction --save changes

测试了这组数据的代码:

Table XXX

id  code
123 456
456 999
789 456;li
932 999;ab
Table YYY

id  x_id
111 789
222 123
333 000
444 932
555 456

运行后:

Table XXX

id  code
123 456
456 999
Table YYY

id  x_id
111 123
222 123
333 000
444 456
555 456
OP,请告诉我它是否适合你。如果您对代码有任何疑问,我很乐意回答。