SQL - 如何从一个表中获取重复记录并连接到另一张表

Posted

技术标签:

【中文标题】SQL - 如何从一个表中获取重复记录并连接到另一张表【英文标题】:SQL - How to get duplicate records from one table with join on another table 【发布时间】:2018-04-13 02:19:06 【问题描述】:

我想从 Table1 中获取记录,其中它有多个相同访问号的记录,但同时该访问号也应该存在于 Table2 中。

例子

表1

    Access Number

 - 1000
 - 1000
 - 1000
 - 2000
 - 3000
 - 4000
 - 5000
 - 5000

表2

AccessNumber  Value

 - 1000       -Value1000
 - 1000       -Value9999
 - 2000       -Value2000
 - 3000       -Value3000

查询的结果应该是1000 - Value1000

这是我目前得到的,请提出建议

SELECT a.AccessNumber, b.Valuefrom Table1 a
JOIN Table2 b on b.AccessNumber = a.AccessNumber
Group by a.AccessNumber, b.VAlue
HAVING COUNT(1) > 1;

我面临的问题是查询返回 Table2 中的重复项。

1000   - Value1000
1000   - Value9999

【问题讨论】:

您使用的是什么版本的 SQL? Table2 中的 CaseReference 字段是什么? @TimBiegeleisen SQL Server 12 @DanieleCappuccio 已编辑 我没有得到任何重复:sqlfiddle.com/#!18/4eade/1 【参考方案1】:

没有太多关于为什么1000 - Value1000 应该是结果而不是1000 - Value9999 的信息,我们可以从顶部获取第一条记录:

select top 1 * from (

-- your original query
SELECT a.AccessNumber, b.Value from Table1 a
JOIN Table2 b on b.AccessNumber = a.AccessNumber
Group by a.AccessNumber, b.Value
HAVING COUNT(1) > 1
-- your original query

) as x;

如果我们只是在寻找具有重复记录的 AccessNumber,您可以从选定的列中删除 b.Value,并在 Group By 子句中将其删除。

SELECT a.AccessNumber from Table1 a
JOIN Table2 b on b.AccessNumber = a.AccessNumber
Group by a.AccessNumber
HAVING COUNT(1) > 1;

http://www.sqlfiddle.com/#!18/3f114/3

【讨论】:

【参考方案2】:

我们或许可以使用 SQL Server 的 EXCEPT 运算符来完成这项工作。但是一个明智的方法是按访问号聚合两个表,然后将第一个连接到第二个,只保留出现在两个表中的访问号 出现的数量更多在第一个比第二个。

SELECT t1.AccessNumber
FROM
(
    SELECT AccessNumber, COUNT(*) AS cnt_1
    FROM Table1
    GROUP BY AccessNumber
) t1
LEFT JOIN
(
    SELECT AccessNumber, COUNT(*) AS cnt_2
    FROM Table2
    GROUP BY AccessNumber
) t2
    ON t1.AccessNumber = t2.AccessNumber
WHERE
    t1.cnt_1 - COALESCE(t2.cnt_2, 0) > 0 AND t2.cnt_2 IS NOT NULL;

Demo

【讨论】:

我实际上是在一个更大的表上运行它,但这会返回比预期更多的记录 @Maverick 不,it works。查看演示。 如何获取Value列? 这个问题没有多大意义。您要为每个访问号码选择哪个值?你现在需要从聚合的角度来讨论,因为上面的报告是两个表的聚合。【参考方案3】:

--希望这个查询对你有帮助

 ; with cte_accessnumber(Accessnumber, [value])
  as
 (
 select 
 t1.Accessnumber, count(*)NoOfRecords
 from table1 t1
 where exists (
 select top 1 1 from table2 t2 where t2.Accessnumber = t1.Accessnumber)
 group by t1.Accessnumber
 having count(*)>1
 )
 select t1.Accessnumber, t2.[value]
 from cte_accessnumber t1
 inner join table2 t2 on t2.Accessnumber = t1.Accessnumber and t2.[value] like '%' + convert(varchar(20),t1.Accessnumber) +'%'

【讨论】:

【参考方案4】:

您可以尝试对 AccessNumber 行 > 1 的条件使用嵌套并交叉应用仅显示 1 条记录的条件

DECLARE @tblA AS TABLE
(
  AccessNumber INT
)
DECLARE @tblB AS TABLE
(
  AccessNumber INT,
  colB NVARCHAR(50)
)
INSERT INTO @tblA SELECT 1000
INSERT INTO @tblA SELECT 1000
INSERT INTO @tblA SELECT 1000
INSERT INTO @tblA SELECT 1000
INSERT INTO @tblA SELECT 2000
INSERT INTO @tblA SELECT 3000
INSERT INTO @tblA SELECT 4000
INSERT INTO @tblB SELECT 1000,'hello'
INSERT INTO @tblB SELECT 1000,'hello2'
INSERT INTO @tblB SELECT 2000,'world'

-- Query --
    SELECT tblB.* FROM (
    SELECT AccessNumber,COUNT(1) AS cnt FROM @tblA GROUP BY AccessNumber ) ftblA 
    CROSS APPLY (SELECT TOP(1) * FROM @tblB itblB WHERE ftblA.AccessNumber = itblB.AccessNumber) tblB
    WHERE ftblA.cnt >1
-- Only 1000 should be displayed only --

【讨论】:

【参考方案5】:

使用subquerycorrelation 方法

select access_no, 
      (select top 1 Value from table2 where access_no = t.access_no) as value
from Table1 t
where exists (
    select 1 from table2 where access_no = t.access_no)
group by access_no
having count(*) > 1

但是,您需要在 subquery 中指定 order by 子句才能从 table2 获取值

【讨论】:

以上是关于SQL - 如何从一个表中获取重复记录并连接到另一张表的主要内容,如果未能解决你的问题,请参考以下文章

Datatable C# - 如何根据 ID 从一个表中获取详细记录及其关联的另一表中的子记录

如何从一个表中获取包含另一表的详细信息的记录计数

PL/SQL - 如何从连接表中返回单行

如何从SQL表中删除不是组的最大值的记录[重复]

sql查询 如何获取查找某ID的一条记录在表中是第几条记录

SQL获取最后一个日期时间记录[重复]