【问题标题】:SQL want to compare value in one cell with part of value in other cellSQL想要将一个单元格中的值与另一个单元格中的部分值进行比较
【发布时间】:2014-11-27 17:42:54
【问题描述】:

我有

表 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 中)

【问题讨论】:

  • 根据给出的答案,我对其进行了一些编辑

标签: sql-server


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

希望这对其他人有帮助。

【讨论】:

  • 很高兴看到您解决了问题!
【解决方案2】:

我在之前的回答中犯了一个错误,因为我给出的解决方案是针对 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

在这组数据上测试了代码:

表 XXX 识别码 123 456 456 999 789 456;李 932 999;ab 表YYY id x_id 111 789 222 123 333 000 444 932 555 456

运行后:

表 XXX 识别码 123 456 456 999 表YYY id x_id 111 123 222 123 333 000 444 456 555 456

OP,如果它对你有用,请告诉我。如果您对代码有任何疑问,我很乐意回答。

【讨论】:

    【解决方案3】:

    第一个查询:

    UPDATE YYY SET X_ID=123 WHERE ID=111
    

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

    第二次查询:

    DELETE FROM XXX WHERE ID=789
    

    【讨论】:

    • 谢谢。我有 2907 条记录需要更新。我更喜欢自动比较这两个值的查询。
    【解决方案4】:

    抱歉,花了一点时间,我找到的唯一快速解决方案是使用程序:

    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; 
    

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

    【讨论】:

    • instr(text,char) 返回字符串文本中找到的字符的索引。
    • 谢谢,MiHaic。我试了又试,终于找到了如何保存存储过程。试图获取正确的元组,但它不会运行,因为但 INSTR 和 SUBSTR '不被识别为内置函数名称'。 (无论这意味着什么)。
    • 我发现 'charindex' 可以替代 instr。现在试图找到一些东西来代替 substr.
    • FOR entry IN ( -> "'in' 附近的语法不正确,需要 ID
    • 明天我的一个朋友过来,我们一起努力寻找解决办法。很抱歉,我无法使用您的解决方案,MiHaic。但它确实激发了我写一个类似的查询,但它仍然有点错误。我会到达那里,所以再次感谢您让我朝着正确的方向前进!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    相关资源
    最近更新 更多