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