多个连接后重复的结果

时间:2017-06-15 15:57:10

标签: sql sql-server join group-by distinct

我尝试过使用distinct关键字,我尝试对列进行分组,但查询仍会返回重复的结果。

SELECT 
distinct orderformdump.itemno,
case when PRH.ACTIVE = 1 and PRH.STARTDATE < cast(GETDATE() as DATE) and (PRH.ENDDATE IS NULL OR PRH.ENDDATE >= cast(GETDATE() as DATE)) then CAST(1 AS BIT) ELSE CAST(0 AS BIT) END as isindeal
FROM ORDERFORMDUMP
INNER JOIN ICITEM ON ICITEM.FMTITEMNO = orderformdump.itemno
LEFT JOIN PRD2 on ICITEM.ITEMNO = PRD2.ITEMNO
LEFT JOIN PRH on PRD2.CODE = PRH.CODE
order by Itemno

重复是由加入,LEFT JOIN PRD2 on ICITEM.ITEMNO = PRD2.ITEMNO或列case when PRH.ACTIVE = 1 and PRH.STARTDATE < cast(GETDATE() as DATE) and (PRH.ENDDATE IS NULL OR PRH.ENDDATE >= cast(GETDATE() as DATE)) then CAST(1 AS BIT) ELSE CAST(0 AS BIT) END as isindeal引起的。我可以删除连接并使用子查询获得相同的结果,但子查询会导致查询运行得非常慢(即使我将列编入索引)。

为什么会有多个结果,我该怎么做才能解决这个问题?

2 个答案:

答案 0 :(得分:1)

试试这个:

SELECT distinct orderformdump.itemno, isnull(tmp.isindeal, CAST(0 AS BIT) ) isindeal
FROM ORDERFORMDUMP
INNER JOIN ICITEM ON ICITEM.FMTITEMNO = orderformdump.itemno
outer apply
(
 select top 1 CAST(1 AS BIT) as isindeal
 from PRD2 INNER JOIN PRH on PRD2.CODE = PRH.CODE 
 where ICITEM.ITEMNO = PRD2.ITEMNO and PRH.ACTIVE = 1  
 and cast(GETDATE() as DATE) between PRH.STARTDATE and isnull(PRH.ENDDATE, cast(GETDATE() as DATE))
) tmp

答案 1 :(得分:1)

要查找问题行,请尝试:

SELECT itemNo, count(*) as dealCount
FROM (
    SELECT 
    distinct orderformdump.itemno,
    case when PRH.ACTIVE = 1 and PRH.STARTDATE < cast(GETDATE() as DATE) and (PRH.ENDDATE IS NULL OR PRH.ENDDATE >= cast(GETDATE() as DATE)) then CAST(1 AS BIT) ELSE CAST(0 AS BIT) END as isindeal
    FROM ORDERFORMDUMP
    INNER JOIN ICITEM ON ICITEM.FMTITEMNO = orderformdump.itemno
    LEFT JOIN PRD2 on ICITEM.ITEMNO = PRD2.ITEMNO
    LEFT JOIN PRH on PRD2.CODE = PRH.CODE
) t
GROUP BY itemNO
ORDER BY dealCount DESC

任何与dealCount和gt; 1表示ICITEM,PRD1或PRH中的多行。然后你应该能够找出你需要消除的东西。

您加入的表格中有多少行?您可以通过稍微更改JOIN来加快速度。你是LEFT JOIN到LEFT JOIN,你并没有真正使用它。由于您只使用PRH.ACTIVE,PRH.STARTDATE和PRH.ENDDATE,因此您可以INNER JOIN PRH到PRD2并减少您左转加入ICITEM的结果集。然后,我猜你的STARTDATE和ENDDATE是DATE数据类型而不是datetime(将getDate()强制转换为DATE)。如果它们是日期时间,您可能需要考虑时间组件。对于你的isindeal,你不需要将1和0作为位。如果您需要显示真或假,只需返回它们并在代码中处理它们。