在 SQL 服务器中使用内部连接检索时如何避免重复记录

How to avoid duplicate records while retrieving using Inner Join in SQL Server

这是我用于打印的存储过程。我面临问题,因为由于评论加入,我得到了两次记录。我想获得如下所述的输出。我是数据库的新手。在这方面的帮助将不胜感激。

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

使用DISTINCT:

Specifies that only unique rows can appear in the result set

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;

如果您的规则变得更加复杂,您希望使用 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 组合的第一行。

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

那你为什么要加入这个table?如果您只想从 eInvoice_tbl_billHistory AS bh 中获取 return 行,并且在 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);

在 select 关键字后使用 Distinct 关键字。