查询返回重复项
Query returning duplicates
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PrintQuickBill](@BillNo int)
AS
SELECT A.BillNo,
A.BillDate,
A.CustomerName,
A.Address,
A.CustomerId,
A.BillLaborAmt,
A.BillPartAmt,
A.ServTaxAmt,
A.VatAmt,
A.BillNetAmt,
FROM dbo.tblQuickBillMain A
INNER JOIN [dbo].tblQuickBillLabor L
ON A.BillNo = L.BillNo
INNER JOIN [dbo].tblQuickBillParts P
ON A.BillNo = P.BillNo
CROSS JOIN dbo.CompanyInfo
WHERE A.BillNo=@BillNo
ORDER BY CustomerName
此SELECT
语句多次return相同的结果。如果我有 1 条记录,结果会显示 3 次。如果我将 @BillNo=1
传递给程序,它应该 return 只有 一行 但它 returns 3 行,它们是相同的。
您的查询与 table CompanyInfo 交叉连接。它返回三行,因为交叉连接 (CompanyInfo) 中的 table 有三行。您没有使用 CompanyInfo 中的任何列,因此我认为不需要该交叉连接。
重复是由以下三种情况之一(或它们的组合)造成的:
- 当CompanyInfo有不止一条记录时(比如3条记录)。
- 当tblQuickBillLabor.BillNo有重复时;
- 当tblQuickBillParts.BillNo有重复时;
您看不到某些结果之间的差异,因为您没有显示 SELECT
列表中其他 table 的任何数据。如果您将其他 table 的列也包含在您的 SELECT
列表中,您会注意到这些列在结果中会有不同的值,其中第一组列会重复。
但是由于您在查询中根本不使用 table CompanyInfo 中的值,因此您应该以任何方式删除查询的 CROSS JOIN CompanyInfo
部分:除非您实际将 table 中的列包含在 SELECT
列表中,否则它没有任何用处。删除它可能已经完全解决了您的问题。
但是,table 名称 tblQuickBillParts 强烈建议您将拥有相同的多个记录 BillNo在那table,否则你不会叫它Parts 复数形式。 table tblQuickBillLabor.
可能也是如此
为了处理这些潜在的问题,由 tblQuickBillLabor.BillNo 和 [= 的连接引起50=]tblQuickBillParts.BillNo,见以下解决方案:
解决方案 A:根本不加入 tables
由于您只从 tblQuickBillMain 中选择值,您最终可能根本不需要加入其他 table,只需写入:
SELECT BillNo,
BillDate,
CustomerName,
Address,
CustomerId,
BillLaborAmt,
BillPartAmt,
ServTaxAmt,
VatAmt,
BillNetAmt,
FROM dbo.tblQuickBillMain
WHERE BillNo=@BillNo
ORDER BY CustomerName
这样你不会得到重复的,但你也会得到在tblQuickBillLabor.BillNo[=91中没有对应记录的记录=] 或 tblQuickBillParts.BillNo。如果该匹配项是必需的,则检查下一个解决方案。
解决方案 B:用子查询替换联接
如果加入 tblQuickBillLabor.BillNo 和 [= 的原因132=] 就是你要确保在那些table中至少有一条匹配的记录,那么用一个WHERE
条件代替BillNo IN (sub query)
:
SELECT BillNo,
BillDate,
CustomerName,
Address,
CustomerId,
BillLaborAmt,
BillPartAmt,
ServTaxAmt,
VatAmt,
BillNetAmt,
FROM dbo.tblQuickBillMain
WHERE BillNo=@BillNo
AND BillNo IN (SELECT BillNo FROM [dbo].tblQuickBillLabor)
AND BillNo IN (SELECT BillNo FROM [dbo].tblQuickBillParts)
ORDER BY CustomerName
请注意,使用此 SQL 语句,您不需要使用 A 为您的 table 设置别名, P, L因为没有歧义。
解决方案 C:不好的 SELECT DISTINCT
从结果集中删除重复项的一种简单但懒惰且不可取的方法是 add the word DISTINCT
紧跟在单词 SELECT
.
之后
用这个 "solution" 你并没有真正找到问题的根源;你只是忽略它并要求一个非重复的结果集。所以,我真的建议选择解决方案 A 或 B,以最适合您的要求为准。
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PrintQuickBill](@BillNo int)
AS
SELECT A.BillNo,
A.BillDate,
A.CustomerName,
A.Address,
A.CustomerId,
A.BillLaborAmt,
A.BillPartAmt,
A.ServTaxAmt,
A.VatAmt,
A.BillNetAmt,
FROM dbo.tblQuickBillMain A
INNER JOIN [dbo].tblQuickBillLabor L
ON A.BillNo = L.BillNo
INNER JOIN [dbo].tblQuickBillParts P
ON A.BillNo = P.BillNo
CROSS JOIN dbo.CompanyInfo
WHERE A.BillNo=@BillNo
ORDER BY CustomerName
此SELECT
语句多次return相同的结果。如果我有 1 条记录,结果会显示 3 次。如果我将 @BillNo=1
传递给程序,它应该 return 只有 一行 但它 returns 3 行,它们是相同的。
您的查询与 table CompanyInfo 交叉连接。它返回三行,因为交叉连接 (CompanyInfo) 中的 table 有三行。您没有使用 CompanyInfo 中的任何列,因此我认为不需要该交叉连接。
重复是由以下三种情况之一(或它们的组合)造成的:
- 当CompanyInfo有不止一条记录时(比如3条记录)。
- 当tblQuickBillLabor.BillNo有重复时;
- 当tblQuickBillParts.BillNo有重复时;
您看不到某些结果之间的差异,因为您没有显示 SELECT
列表中其他 table 的任何数据。如果您将其他 table 的列也包含在您的 SELECT
列表中,您会注意到这些列在结果中会有不同的值,其中第一组列会重复。
但是由于您在查询中根本不使用 table CompanyInfo 中的值,因此您应该以任何方式删除查询的 CROSS JOIN CompanyInfo
部分:除非您实际将 table 中的列包含在 SELECT
列表中,否则它没有任何用处。删除它可能已经完全解决了您的问题。
但是,table 名称 tblQuickBillParts 强烈建议您将拥有相同的多个记录 BillNo在那table,否则你不会叫它Parts 复数形式。 table tblQuickBillLabor.
可能也是如此为了处理这些潜在的问题,由 tblQuickBillLabor.BillNo 和 [= 的连接引起50=]tblQuickBillParts.BillNo,见以下解决方案:
解决方案 A:根本不加入 tables
由于您只从 tblQuickBillMain 中选择值,您最终可能根本不需要加入其他 table,只需写入:
SELECT BillNo,
BillDate,
CustomerName,
Address,
CustomerId,
BillLaborAmt,
BillPartAmt,
ServTaxAmt,
VatAmt,
BillNetAmt,
FROM dbo.tblQuickBillMain
WHERE BillNo=@BillNo
ORDER BY CustomerName
这样你不会得到重复的,但你也会得到在tblQuickBillLabor.BillNo[=91中没有对应记录的记录=] 或 tblQuickBillParts.BillNo。如果该匹配项是必需的,则检查下一个解决方案。
解决方案 B:用子查询替换联接
如果加入 tblQuickBillLabor.BillNo 和 [= 的原因132=] 就是你要确保在那些table中至少有一条匹配的记录,那么用一个WHERE
条件代替BillNo IN (sub query)
:
SELECT BillNo,
BillDate,
CustomerName,
Address,
CustomerId,
BillLaborAmt,
BillPartAmt,
ServTaxAmt,
VatAmt,
BillNetAmt,
FROM dbo.tblQuickBillMain
WHERE BillNo=@BillNo
AND BillNo IN (SELECT BillNo FROM [dbo].tblQuickBillLabor)
AND BillNo IN (SELECT BillNo FROM [dbo].tblQuickBillParts)
ORDER BY CustomerName
请注意,使用此 SQL 语句,您不需要使用 A 为您的 table 设置别名, P, L因为没有歧义。
解决方案 C:不好的 SELECT DISTINCT
从结果集中删除重复项的一种简单但懒惰且不可取的方法是 add the word DISTINCT
紧跟在单词 SELECT
.
用这个 "solution" 你并没有真正找到问题的根源;你只是忽略它并要求一个非重复的结果集。所以,我真的建议选择解决方案 A 或 B,以最适合您的要求为准。