【问题标题】:How to avoid duplicate records while retrieving using Inner Join in SQL Server如何在 SQL Server 中使用内部联接检索时避免重复记录
【发布时间】:2016-03-06 15:30:20
【问题描述】:

这是我用于打印的存储过程。我正面临问题,因为由于评论加入,我获得了两倍的记录。我想获得如下所述的输出。我是 DB 的新手。我们将不胜感激。

DECLARE @path AS VARCHAR(100)
SET @path = N'~/BillAttachments/166/'
DECLARE @billID AS INT
SET @billID = 166

SELECT bh.billID,bh.statusID,bh.modifiedOn,bs.statusName
FROM dbo.eInvoice_tbl_billHistory AS bh
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON bh.billID = ba.billID
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON ba.billID = bh.billID
INNER JOIN dbo.eInvoice_tbl_billStatus AS bs ON bh.statusID = bs.statusID
WHERE bh.billID=@billID;

当我尝试从所需的表中获取这些列时

ba.attachmentID ,
        @path + ba.fileName AS asad ,
        ba.attachmentDescription ,
        ba.billAttachmentStatus,

输出是:

166 3   2015-11-30 11:44:18.663 Approve
166 3   2015-11-30 11:44:18.663 Approve
166 5   2015-11-30 11:44:42.600 Paid
166 5   2015-11-30 11:44:42.600 Paid

但想要的输出是:

166 3   2015-11-30 11:44:18.663 Approve
166 5   2015-11-30 11:44:42.600 Paid

【问题讨论】:

  • 您应该调查数据以找出您得到重复项的原因。虽然您可以通过修改查询来解决问题(例如,使用select distinct),但您应该确保数据正确且不包含重复项。
  • 请再次查看问题,已修改

标签: sql sql-server database stored-procedures inner-join


【解决方案1】:

使用DISTINCT:

指定结果集中只能出现唯一的行

SELECT DISTINCT bh.billID,bh.statusID,bh.modifiedOn,bs.statusName 
FROM dbo.eInvoice_tbl_billHistory AS bh
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON bh.billID = ba.billID
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON ba.billID = bh.billID
INNER JOIN dbo.eInvoice_tbl_billStatus AS bs ON bh.statusID = bs.statusID
WHERE bh.billID=@billID;

其他方法是使用GROUP BY:

SELECT bh.billID,bh.statusID,bh.modifiedOn,bs.statusName 
FROM dbo.eInvoice_tbl_billHistory AS bh
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON bh.billID = ba.billID
--INNER JOIN dbo.eInvoice_tbl_billAttachment AS ba ON ba.billID = bh.billID
INNER JOIN dbo.eInvoice_tbl_billStatus AS bs ON bh.statusID = bs.statusID
WHERE bh.billID=@billID
GROUP BY bh.billID,bh.statusID,bh.modifiedOn,bs.statusName;

【讨论】:

  • 您也可以执行 SELECT ... UNION 相同的 SELECT 以获得不同的值。
【解决方案2】:

如果您的规则越来越复杂,您希望使用 CTE 和 ROW_NUMBER 排名函数继续保留哪一行:

WITH CTE AS
(
    SELECT bh.billID, 
           bh.statusID, 
           bh.modifiedOn, 
           bs.statusName,
           rn = ROW_NUMBER() OVER() (PARTITION BY bh.billID, bh.statusID ORDER BY bh.modifiedOn ASC)
    FROM   dbo.eInvoice_tbl_billHistory AS bh 
           INNER JOIN dbo.eInvoice_tbl_billStatus AS bs 
                   ON bh.statusID = bs.statusID 
    WHERE  bh.billID = @billID; 
)
SELECT billID, statusID, modifiedOn, statusName
FROM CTE 
WHERE RN = 1

在此示例中,我根据 modifiedOn 日期时间保留每个 BillId+StatusID 组合的第一行。

【讨论】:

    【解决方案3】:

    在您的代码中,您使用 eInvoice_tbl_billAttachment AS ba 加入,但未在 select 语句中使用它。您提到这似乎是导致重复行的原因,所以我猜这个表中有 2 行 billID = 166。

    那你为什么要加入这张桌子?如果您只想从 eInvoice_tbl_billHistory AS bh 返回在 ba 中也至少有一行的行,您可以使用 exists 语句来代替:

    DECLARE @path AS VARCHAR(100)
    SET @path = N'~/BillAttachments/166/'
    DECLARE @billID AS INT
    SET @billID = 166
    
    SELECT bh.billID,bh.statusID,bh.modifiedOn,bs.statusName
    FROM dbo.eInvoice_tbl_billHistory AS bh
    INNER JOIN dbo.eInvoice_tbl_billStatus AS bs ON bh.statusID = bs.statusID
    WHERE bh.billID=@billID 
    AND exists (select 1 from dbo.eInvoice_tbl_billAttachment AS ba 
                where  bh.billID = ba.billID);
    

    【讨论】:

      【解决方案4】:

      在选择关键字后使用 Distinct Keyword。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-20
        • 1970-01-01
        • 1970-01-01
        • 2012-03-24
        • 2017-07-12
        • 1970-01-01
        相关资源
        最近更新 更多