【问题标题】:eliminating rows with opposing values消除具有相反值的行
【发布时间】:2017-04-02 13:46:48
【问题描述】:

例如,我想消除具有相反值的行 我的表中有以下行

id     value1  value2  value3
----   ------  ------  -------
10     -1        -20     -48.5
10      1         20      48.5
10     -1        -30     -26.2
10      1         30      26.2
10      1         27      30.5

我想得到的是

id     value1  value2  value3
----   ------  ------  -------
10      1         27      30.5

任何建议将不胜感激。

【问题讨论】:

  • 如果你有两行像1,20,48.5,而只有一行像-1,-20,-48.5
  • 有趣的是没有人尝试过设置方法......除了。假设值 1,2,3 相同,只是首先通过正面进行负面过滤,然后删除所有具有匹配负面声音的内容,如原生 SQL 方法(尽管除了 / intersect 是相当新的)

标签: sql sql-server tsql


【解决方案1】:

由于您需要排除(删除)相反的行,解决方案是制作一个 CTE 来获取所有这些记录并删除它们:

drop table if exists #a
create table #a (id int, value1 INT, value2 INT, value3 FLOAT)
INSERT INTO #a
VALUES 
(10,     -1,        -20,     -48.5),
(10,      1,         20,      48.5),
(10,     -1,        -30,     -26.2),
(10,      1,         30,      26.2),
(10,      1,         27,      30.5)

;with duplicateRows as (
    select a1.id
    from #a a1
    where exists ( --Verify the results with opposites
        select * from #a a2
        where
            a1.id = a2.id
            and a1.value1 = - a2.value1
            and a1.value2 = - a2.value2
            and a1.value3 = - a2.value3
        )
    )
delete duplicateRows --> Make a select first for test!

select * from #a --> The row of value2 = 27 is the only one now

【讨论】:

  • 他没有说删除 - 他说消除。就像查询结果一样。
【解决方案2】:
/*
Compare the Table to itself to look for opposite values.
You can achieve that by multiplying the value of the second table by -1, looking for the opposite.
Since you did not specified if all or some of the values have to be opposites, i assumed they all must be opposites, and that's why I use AND in the JOIN.
If the condition is met just by any value, then change the AND by OR in the JOIN.
*/

DECLARE     @MyTable    TABLE   (id int, value1 int, value2 int, value3 numeric(5,1))
INSERT INTO @MyTable    VALUES
            (10, -1, -20, -48.5)
        ,   (10,  1,  20,  48.5)
        ,   (10, -1, -30, -26.2)
        ,   (10,  1,  30,  26.2)
        ,   (10,  1,  27,  30.5)
;

SELECT          T1.*

FROM            @MyTable    T1
    LEFT JOIN   @MyTable    T2  ON  (T2.value1 = -1 * T1.value1)
                                AND (T2.value2 = -1 * T1.value2)
                                AND (T2.value3 = -1 * T1.value3)
WHERE   T2.id   IS NULL

【讨论】:

  • 欢迎来到 Stack Overflow。没有任何解释的代码转储很少有帮助。 Stack Overflow 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请edit您的问题并解释它如何比OP提供的更好。
【解决方案3】:

这个怎么样:

DECLARE @T TABLE (
    id INT,
    value1 INT,
    value2 INT,
    value3 DECIMAL(9,2)
)

INSERT @T VALUES
(10, -1, -20, -48.5),
(10, 1, 20, 48.5),
(10, 1, -20, -48.5),
(10, -1, 20, 48.5),
(10, -1, -30, -26.2),
(10, 1, 30, 26.2),
(10, 1, 27, 30.5)

SELECT A.* FROM @T A
LEFT JOIN @T B ON
    B.id = A.id
    AND B.value1 = -A.value1
    AND B.value2 = -A.value2
    AND B.value3 = -A.value3
WHERE B.id IS NULL

【讨论】:

    【解决方案4】:

    我返回的是正数。然后我对所有字段进行分组,只返回单行字段。您可以在选择中使用MINMAX。两者都会返回正确的结果。

    DECLARE @Tbl TABLE (id INT, value1 INT, value2 INT, value3 FLOAT)
    
    INSERT INTO @Tbl        
    VALUES 
    (10,     -1,        -20,     -48.5),
    (10,      1,         20,      48.5),
    (10,     -1,        -30,     -26.2),
    (10,      1,         30,      26.2),
    (10,      1,         27,      30.5)
    
    
    SELECT
        T.id ,
        MIN(T.value1) ,
        MIN(T.value2),
        MIN(T.value3)
    FROM
        @Tbl T
    GROUP BY
        T.id ,
        ABS(T.value1) ,
        ABS(T.value2),
        ABS(T.value3) HAVING COUNT(1) = 1
    

    结果:

    id  value1  value2  value3
    10  1       27      30.5
    

    我建议您在更大的数据上进行测试。您可能会遇到性能问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      • 2023-03-27
      • 2017-03-02
      • 1970-01-01
      • 2017-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多