2014-11-04 74 views
0

我有这个表:SQL查询同一个表内连接消除重复

CREATE TABLE [BGIA].[INTCOL004VA](
[ID] [int] NOT NULL, 
[DATYEN] [varchar](18) NULL, 
[ZZRIDN] [varchar](8) NULL, 
[OQTIEF] [varchar](1) NULL, 
[OQMONE] [varchar](3) NULL, 
[ZZPONR] [varchar](3) NULL, 
[ZZNBRE] [varchar](15) NULL, 
[ZZPDSE] [varchar](22) NULL 
); 

    INSERT INTO INTCOL004VA VALUES 
('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'), 
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'), 
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500'), 
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'), 
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0'), 
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'), 
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0'); 

记录由DATYEN,ZZRIDN和ZZPONR

我想这个规则更新表链接:

  • 对于一个链接DATYEN,ZZRIDN如果ZZNBRE上的一行不是0并且ZZPDSE => OQTIEF = 0并且OQMONE = NULL
  • 但是对于一个链接DATYNE,ZZRIDN如果所有行都是a在ZZNBRE和ZZPDSE和一个行r 0有OQTIEF = 1和OQMONE不是null =>适用于所有的行AF链接OQTIEF = 1和OQMONE =不空行

我不能做的OQMONE与INNER JOIN突然,我不知道如何成功

谢谢:)

编辑:对于为例,这样的:

('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'), 
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'), 
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500') 

必须是:

('53671955', 'MC1141103006', '38565363', '0', NULL, '010', '0', '0'), 
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'), 
('53671957', 'MC1141103006', '38565363', '0', NULL, '030', '1', '500') 

因为组MC1141103006和38565363有一行与ZZNBRE和ZZPDSE不为0

此:

('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'), 
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0') 

必须是:

('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'), 
('53671961', 'ST1141103006', '38587542', '0', NULL, '020', '0', '0') 

因为组ST1141103006和38587542有一排用ZZNBRE和ZZPDSE不是0,而是将ZZNBRE设置为0,因为ZZPDSE为0

这:

('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'), 
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0') 

必须是:

('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'), 
('53671959', 'VT1141103010', '38565421', '1', '007', '100', '0', '0') 

因为所有的行具有ZZNBRE和ZZNBRE 0

我希望能准确地说,是不容易理解我猜:(

编辑2:其实我的查询是:

update v1 
set v1.zznbre = (case when v1.zzpdse = 0 then 0 else v1.zznbre end), 
v1.oqtief = (case when v1.zznbre = 0 and v2.zznbre = 0 and v1.zzpdse = 0 and v2.zzpdse = 0 then 1 else 0 end), 
v1.oqmone = (case when v1.zznbre = 0 and v2.zznbre = 0 and v1.zzpdse = 0 and v2.zzpdse = 0 then v2.oqmone else null end) 
from intcol004va v1 
inner join intcol004va v2 on v2.datyen = v1.datyen and v2.zzridn = v1.zzridn and v2.id <> v1.id 
where v2.oqtief = 1 and v2.oqmone is not null and v1.oqtief <> v2.oqtief 

但在所有情况下无法正常工作:(

+2

你能解释一下更新规则吗?目前还不清楚 – 2014-11-04 13:34:30

+1

您可以请用正常名字吗? – SubqueryCrunch 2014-11-04 13:39:57

+2

欢迎来到Stack Overflow!我们很高兴见到你:)这样发布你的全表结构非常有帮助,我们非常感谢。正如其他人指出的,但是,你的问题有点难以理解。你能告诉我们任何SQL或样本数据,这将使你的规则更清晰一些吗?也许建立一个SQL Fiddle示例,以便我们可以看到你在说什么? – AHiggins 2014-11-04 13:48:01

回答

0

如果将更新作为两个独立更新进行处理,它似乎会生成正确的答案集。 我包含一个结果表和代码,它将显示原始数据与您的描述中定义的所需结果表之间的比较。

接下来,它将执行两次更新,然后显示已加入的原始表和目标表,以证明它们已正确对齐。

CREATE TABLE [INTCOL004VA](
[ID] [int] NOT NULL, 
[DATYEN] [varchar](18) NULL, 
[ZZRIDN] [varchar](8) NULL, 
[OQTIEF] [varchar](1) NULL, 
[OQMONE] [varchar](3) NULL, 
[ZZPONR] [varchar](3) NULL, 
[ZZNBRE] [varchar](15) NULL, 
[ZZPDSE] [varchar](22) NULL 
); 

CREATE TABLE [R_INTCOL004VA](
[ID] [int] NOT NULL, 
[DATYEN] [varchar](18) NULL, 
[ZZRIDN] [varchar](8) NULL, 
[OQTIEF] [varchar](1) NULL, 
[OQMONE] [varchar](3) NULL, 
[ZZPONR] [varchar](3) NULL, 
[ZZNBRE] [varchar](15) NULL, 
[ZZPDSE] [varchar](22) NULL 
); 

INSERT INTO INTCOL004VA VALUES 
('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'), 
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'), 
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500'), 
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'), 
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0'), 
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'), 
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0'); 

INSERT INTO [R_INTCOL004VA] VALUES 
('53671955', 'MC1141103006', '38565363', '0', NULL, '010', '0', '0'), 
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'), 
('53671957', 'MC1141103006', '38565363', '0', NULL, '030', '1', '500'), 
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'), 
('53671961', 'ST1141103006', '38587542', '0', NULL, '020', '0', '0'), 
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'), 
('53671959', 'VT1141103010', '38565421', '1', '007', '100', '0', '0') 


SELECT 
    D.ID, 
    D.DATYEN, 
    D.ZZRIDN, 
    D.OQTIEF, 
    E.OQTIEF AS CORRECT_OQTIEF, 
    D.OQMONE, 
    E.OQMONE AS CORRECT_OQMONE, 
    D.ZZPONR, 
    D.ZZNBRE, 
    D.ZZPDSE 
FROM 
    INTCOL004VA AS D 
INNER JOIN 
    R_INTCOL004VA AS E ON D.ID = E.ID 

UPDATE 
    INTCOL004VA 
SET 
    OQTIEF = 0, 
    OQMONE = NULL 
FROM 
    INTCOL004VA AS A 
INNER JOIN 
    (SELECT 
     B.DATYEN, 
     B.ZZRIDN 
    FROM 
     INTCOL004VA AS B 
    GROUP BY 
     B.DATYEN, 
     B.ZZRIDN 
    HAVING 
     SUM(CAST(B.ZZNBRE AS INT)) > 0 
    ) AS C ON A.DATYEN = C.DATYEN AND A.ZZRIDN = C.ZZRIDN 


UPDATE 
    INTCOL004VA 
SET 
    OQTIEF = 1, 
    OQMONE = C.OQMONE 
FROM 
    INTCOL004VA AS A 
INNER JOIN 
    (SELECT 
     B.DATYEN, 
     B.ZZRIDN, 
     MAX(ISNULL(B.OQMONE,'')) AS OQMONE 
    FROM 
     INTCOL004VA AS B 
    GROUP BY 
     B.DATYEN, 
     B.ZZRIDN 
    HAVING 
     SUM(CAST(B.OQTIEF AS INT)) > 0 
    ) AS C ON A.DATYEN = C.DATYEN AND A.ZZRIDN = C.ZZRIDN 


SELECT 
    D.ID, 
    D.DATYEN, 
    D.ZZRIDN, 
    D.OQTIEF, 
    E.OQTIEF AS CORRECT_OQTIEF, 
    D.OQMONE, 
    E.OQMONE AS CORRECT_OQMONE, 
    D.ZZPONR, 
    D.ZZNBRE, 
    D.ZZPDSE 
FROM 
    INTCOL004VA AS D 
INNER JOIN 
    R_INTCOL004VA AS E ON D.ID = E.ID 

有时只是把它分解成更小的块是更容易的方法来解决问题。

+0

不可能在一个查询中? :( – cerede2000 2014-11-05 10:16:15

+0

我确信它可以在一个动作中完成,但是这个问题会变得复杂和可读性,不仅仅是为了你自己,而且还是下一个开发者必须在你后面维护这个脚本。在这两种力量之间,通常我们会倾向于稍微慢一些的代码,这些代码更容易维护,更容易验证。准确性比剃须和额外的3ms更重要。据说我确实很享受能够编写一个超级复杂的查询因为这是一个挑战,我认为我可以做到这一点,但是当我这样做时,我的开发人员会讨厌我。 – 2014-11-05 14:57:44

+0

@BenjaminCEREDE你总是可以将所有事务都包装在一个事务中 – Horaciux 2014-11-05 15:45:51