2017-08-02 95 views
1

我有一个奇怪的问题:我有两个表,我希望加入一个联盟。我不希望任何重复列,但每个表都有一个额外的变量我写到哪儿来的SELECT子句指定来自:SQL:在所有EXCEPT指定的列中除外重复预防

SELECT EOU.EventSessionKey, EOU.EventSourceID, EOU.EventSeq, 
    EOU.EventColumnName, EOU.ProSymbol, 
    EOU.ProKey, tP.isActive, tP.Description, 
    'POSITIVE' AS ErrType FROM EOU 
LEFT JOIN dbRunoff.dbo.tPro tP 
    ON tP.Symbol COLLATE DATABASE_DEFAULT 
     = EOU.ProSymbol COLLATE DATABASE_DEFAULT 
WHERE tP.IsActive = 1 AND (EOU.ProKey IS NULL OR EOU.ProKey <= 0) 

UNION 

SELECT EOU.EventSessionKey, EOU.EventSourceID, EOU.EventSeq, 
    EOU.EventColumnName, EOU.ProSymbol, 
    EOU.ProKey, tP.isActive, tP.Description, 
    'DUPLICATE' AS ErrType FROM EOU 
LEFT JOIN dbRunoff.dbo.tPro tP 
    ON tP.Symbol COLLATE DATABASE_DEFAULT 
     = EOU.ProSymbol COLLATE DATABASE_DEFAULT 
JOIN ProFilter PF ON PF.ProKey = tp.ProKey 
WHERE tP.IsActive = 1 AND (EOU.ProKey IS NULL OR EOU.ProKey <= 0)) 

我担心在最后添加的文本变量将阻止联盟函数正确删除重复值。是否有任何(简单/有效)的方式确保联合删除表间重复的值,但忽略文本变量,否则会导致联合不读取重复项?

请注意,我正在寻找简单的方法来做到这一点。我知道一些强制性的方法,但是效率和速度都令人担忧。

+0

好,如果它是一个重复的,你会要归因于最后一栏为你保留该行该值(仅最后一列是唯一的) ?积极还是重复? – scsimon

+0

'重复',该名称引用了我正在跟踪的特定类型的事件,所以我想要抓住那个'积极',这是一个捕获所有事件。 –

+1

重复出现在子查询中吗? 'union'删除组件之间和组件之间的重复。 –

回答

3

既然你想要重复的,你可以使用MIN()CTED之前P因此加入将使用重复当它存在超过积极

只是一个侧面说明,我要重写这个没有UNION

with cte as(
SELECT EOU.EventSessionKey, EOU.EventSourceID, EOU.EventSeq, 
    EOU.EventColumnName, EOU.ProSymbol, 
    EOU.ProKey, tP.isActive, tP.Description, 
    'POSITIVE' AS ErrType FROM EOU 
LEFT JOIN dbRunoff.dbo.tPro tP 
    ON tP.Symbol COLLATE DATABASE_DEFAULT 
     = EOU.ProSymbol COLLATE DATABASE_DEFAULT 
WHERE tP.IsActive = 1 AND (EOU.ProKey IS NULL OR EOU.ProKey <= 0) 

UNION 

SELECT EOU.EventSessionKey, EOU.EventSourceID, EOU.EventSeq, 
    EOU.EventColumnName, EOU.ProSymbol, 
    EOU.ProKey, tP.isActive, tP.Description, 
    'DUPLICATE' AS ErrType FROM EOU 
LEFT JOIN dbRunoff.dbo.tPro tP 
    ON tP.Symbol COLLATE DATABASE_DEFAULT 
     = EOU.ProSymbol COLLATE DATABASE_DEFAULT 
JOIN ProFilter PF ON PF.ProKey = tp.ProKey 
WHERE tP.IsActive = 1 AND (EOU.ProKey IS NULL OR EOU.ProKey <= 0)) 

select distinct 
    EventSessionKey 
    ,EventSourceID 
    ,EventSeq 
    ,EventColumnName 
    ,ProSymbol 
    ,ProKey 
    ,isActive 
    ,Description 
    ,min(cte2.ErrType) 
from 
    cte 
    left join 
    cte2 on cte.EventSessionKey = cte2.SessionKey --assumption based of column name. Use correct key to join. 
group by 
    EventSessionKey 
    ,EventSourceID 
    ,EventSeq 
    ,EventColumnName 
    ,ProSymbol 
    ,ProKey 
    ,isActive 
    ,Description 

编辑

这应该给你基于相同的事情,我在你的查询看到什么...基本上,我对ProFilter改变了你的INNER JOIN为左连接。如果此加入结果为TRUE,那么根据您的UNION,它应该是重复记录。如果它不存在,这将是

SELECT 
    EOU.EventSessionKey, 
    EOU.EventSourceID, 
    EOU.EventSeq, 
    EOU.EventColumnName, 
    EOU.ProSymbol, 
    EOU.ProKey, 
    tP.isActive, 
    tP.Description, 
    case when pf.ProKey is null then 'Positive' else 'Duplicate' end as ErrType 
FROM 
    EOU 
LEFT JOIN 
    dbRunoff.dbo.tPro tP 
    ON tP.Symbol COLLATE DATABASE_DEFAULT = EOU.ProSymbol COLLATE DATABASE_DEFAULT 
LEFT JOIN 
    ProFilter PF 
    ON PF.ProKey = tp.ProKey 
WHERE 
    tP.IsActive = 1 
    AND (EOU.ProKey IS NULL OR EOU.ProKey <= 0) 
+0

更容易围绕第二个人围绕我的大脑+1 –

+0

我同意@JohnCappelletti解构查询后,告诉差异我看到为什么OP认为工会是必要的,但这是我使用的最稀有的事情之一。 – scsimon

+0

LEFT JOIN逻辑不等同于UNION查询。你必须从FULL OUTER JOIN开始,然后比较每个字段的相等/无效性,以实际模拟一个简单的UNION。在下面看到我的答案(很快)。 –