【问题标题】:MSSQL get rows which only differ at 2 columnsMSSQL 获取仅在 2 列处不同的行
【发布时间】:2018-08-15 06:30:13
【问题描述】:

我有一个任务,我什至不知道它是如何完成的。

我必须找到时差为 X 且布尔值为 ON/OFF 的记录。我尝试使用 LEFT OUTER JOIN 并使用 ON 子句中的条件,但它给了我错误的结果。

所以我的问题是,我怎样才能选择在 2 列中具有相同值但在其他 2 列中具有不同值的行?

编辑: 我的问题是,由于某种原因,我的实际查询多次返回相同的条目。我检查了该条目是否存在多次,但它不存在


参考数据:

ID1   ID2   Boolean   Time
 1     1       0      2018-03-06 11:31:39
 1     1       1      2018-03-06 11:33:39
 2     1       0      2018-03-06 11:31:39
 2     2       1      2018-03-06 11:40:39

查询的期望输出是

ID1   ID2   Boolean   Time
 1     1       0      2018-03-06 11:31:39
 1     1       1      2018-03-06 11:33:39

因为 ID1 和 ID2 相同,所以布尔值不同,时间差在指定范围内(比如说 5 分钟)。其他2条无效,因为ID2不同,时间差太大。

我当前的查询:

select 
t1.id1,
t1.id2,
t1.boolean,
t1.time
from t1 t1
left outer join t1 t2
on t1.boolean != t2.boolean and datediff(minute, t1.time, t2.time)<=5
where t1.id1 = t2.id1
and t1.id2 = t2.id2

【问题讨论】:

  • 您的查询是正确的,有什么问题
  • 查询有什么问题?对于给定的数据,它给出了与您提到的相同的输出。只有一个错误and t.id2 = t2.id2t 更改为t1
  • left join改成inner join,这里也不需要左连接
  • 这是由于left join 可能将其更改为inner join 并尝试
  • 即使使用inner join,我也至少得到每个条目 2 次​​span>

标签: sql sql-server join where


【解决方案1】:

您的查询看起来不错,我发现了一些小问题

1- 使用的表别名错误,而不是t,应该是t1

2- 顺序或数据错误

3- 将left join 更改为inner join

4- 修改 ONWhere 条件以获得更好的可读性和性能

检查以下更正后的查询。

WITH t1 AS 
(
 SELECT * FROM (VALUES 

 (1   ,  1     ,  0     , '2018-03-06 11:31:39'),
 (1   ,  1   ,    1    ,  '2018-03-06 11:33:39'),
 (2   ,  1   ,    0    ,  '2018-03-06 11:31:39'),
 (2   ,  2   ,    1    ,  '2018-03-06 11:40:39')
  ) T(  ID1,   ID2 ,  Boolean,   Time)
)

select 
t1.id1,
t1.id2,
t1.boolean,
t1.time
from t1 t1
inner  join t1 t2
on t1.id1 = t2.id1  and t1.id2 = t2.id2 
where 
t1.boolean != t2.boolean and datediff(minute, t1.time, t2.time)<=5
ORDER BY [TIME] 

输出

+-----+-----+---------+---------------------+
| id1 | id2 | boolean | time                |
+-----+-----+---------+---------------------+
| 1   | 1   | 0       | 2018-03-06 11:31:39 |
+-----+-----+---------+---------------------+
| 1   | 1   | 1       | 2018-03-06 11:33:39 |
+-----+-----+---------+---------------------+

【讨论】:

  • 似乎我还有另一个问题,因为我的查询多次返回相同的条目。我什至重写了查询以仅包含此处给出的内容,并且仍然包含多个条目。这些条目甚至在任何地方都没有区别
  • 这很奇怪,对于给定的数据和查询,它应该只返回两行。您是否执行了示例 CTE 代码?输出是什么
  • 我无法共享数据。测试代码确实给出了正确的结果
【解决方案2】:

为避免重复值使用GROUP BY

SELECT t1.id1
    ,t1.id2
    ,t1.boolean
    ,t1.TIME
FROM t1 t1
INNER JOIN t1 t2 ON t1.boolean != t2.boolean
    AND datediff(minute, t1.TIME, t2.TIME) <= 5
WHERE t1.id1 = t2.id1
    AND t1.id2 = t2.id2
GROUP BY t1.id1
    ,t1.id2
    ,t1.boolean
    ,t1.TIME

【讨论】:

  • 分组也不起作用。它确实消除了重复项,但输出仍然错误
  • 它仍然没有为我的数据提供所需的结果。我需要显示示例输出中显示的内容。然而我只得到其中的 1 行
  • 怎么可能?对于给定的数据,当我应用 group by 它工作正常并按预期给出 2 个结果?
  • 如果您能以我们可以重现问题的方式修改样本数据,我们将不胜感激,我们知道这是机密信息,但您可以修改数据并与我们共享...无需适当没有人会帮助你的数据
  • 您真的想要 140 列的样本数据吗?我不为所有人提供示例数据的唯一原因是列的绝对数量
【解决方案3】:
SELECT
    D1.*
FROM
    Data AS D1
WHERE
    EXISTS (
        SELECT
            1
        FROM
            Data AS D2
        WHERE
            D1.ID1 = D2.ID2 AND
            ~D1.Boolean = D2.Boolean AND
            ABS(DATEDIFF(MINUTE, D1.Time, D2.Time)) <= 5)
ORDER BY
    D1.ID1,
    D1.Boolean,
    D1.Time

【讨论】:

    猜你喜欢
    • 2016-10-18
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多