SQL需要从联盟中删除重复项

时间:2018-06-27 17:59:15

标签: sql tsql duplicates union

我正在写一个查询。它从几个不同的表中收集一些数据,并求和和一些平均值。 最初,我的客户要求我根据某些标准进行选择,从零件的整体列表中进行限制,但是,现在,该客户希望能够显示所有项目,即使它们不属于该标准。 我遇到的问题是,我的初始查询显然限制了选择,因为它需要使用where子句来确定某些条件(例如,基于类别,仅当结果为负数时才包括结果,而在正数时不包括结果)并且在尝试使用并集时,只要符合条件,我都会得到重复的条目。意思是,我的第二个Select可以获取所有内容,但是当它已经从第一个中添加时,并没有过滤掉该条目。 Union并不认为这些是不同的,因为即使零件编号匹配,计算字段也不同。

我试图做一组相反的Where条件,这些条件将简单地获得初始选择的镜像,从而消除了重复的可能性,但是,我找不到正确的条件。

我可以帮忙为以下一组Where条件做出相反的选择吗(两个除法参数都必须相同,但是为其他条件创建相反的条件可能有效,我只是不能找出方法):

WHERE(iitt.Name = 'Invoicing'
      OR iitt.Name = 'Issuing'
      OR (iitt.Name = 'Post Worksheet'
          AND iit.quantity <= 0))
     AND iit.TransactionDate BETWEEN @StartDate AND @EndDate
     AND id.DivisionFK = @division
     AND iit.DivisionNumber = @division

或者是否有某种方法可以根据并集中某个字段中的某个匹配项来明确选择,而不是对每个字段都使用相同的匹配项,这是并集筛选结果的唯一标准?选择Distinct或Top 1不起作用。完整的代码如下:

DECLARE @startdate DATE, @enddate DATE, @division INT;
SET @startdate = '5/23/2018';
SET @enddate = '6/26/2018';
SET @division = 2;
SELECT i.PartNumber AS 'Part Number',
       CONVERT(DOUBLE PRECISION, CAST(ABS(SUM(iit.quantity)) AS DECIMAL(19, 0))) AS 'Sum Quantity',
       CONVERT(DOUBLE PRECISION, id.quantityOnHand) AS 'Division Quantity on Hand',
       CASE
           WHEN SUM(iit.quantity) = 0
           THEN 0
           WHEN DATEPART(DAYOFYEAR, @enddate) - DATEPART(DAYOFYEAR, @startdate) = 0
           THEN 0
           WHEN YEAR(@enddate) - YEAR(@startdate) = 1
           THEN CONVERT(DOUBLE PRECISION, CAST(ABS((SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate)))) AS DECIMAL(19, 2)))
           WHEN YEAR(@enddate) - YEAR(@startdate) = 2
           THEN CONVERT(DOUBLE PRECISION, CAST(ABS(SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate) + 364)) AS DECIMAL(19, 2)))
           ELSE CONVERT(DOUBLE PRECISION, CAST(ABS(SUM(iit.quantity) / (DATEPART(DAYOFYEAR, @enddate) - DATEPART(DAYOFYEAR, @startdate))) AS DECIMAL(19, 2)))
       END AS 'Avg Use Per Day',
       CASE
           WHEN SUM(iit.quantity) = 0
           THEN NULL
           WHEN SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate)) = 0
           THEN 0
           WHEN SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate) + 364) = 0
           THEN 0
           WHEN SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate) + 364) = 0
           THEN 0
           WHEN SUM(iit.quantity) / (DATEPART(DAYOFYEAR, @enddate) - DATEPART(DAYOFYEAR, @startdate)) = 0
           THEN 0
           WHEN YEAR(@enddate) - YEAR(@startdate) = 1
           THEN CONVERT(DOUBLE PRECISION, CAST(ABS(ROUND(id.quantityOnHand / ((SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate)))), 2)) AS DECIMAL(19, 2)))
           WHEN YEAR(@enddate) - YEAR(@startdate) = 2
           THEN CONVERT(DOUBLE PRECISION, CAST(ABS(ROUND(id.quantityOnHand / (SUM(iit.quantity) / ((364 - DATEPART(DAYOFYEAR, @startdate)) + DATEPART(DAYOFYEAR, @enddate) + 364)), 2)) AS DECIMAL(19, 2)))
           ELSE CONVERT(DOUBLE PRECISION, CAST(ABS(ROUND(id.quantityOnHand / (SUM(iit.quantity) / (DATEPART(DAYOFYEAR, @enddate) - DATEPART(DAYOFYEAR, @startdate))), 2)) AS DECIMAL(19, 2)))
       END AS 'Depletion Days per Avg Use',
       CONVERT(DOUBLE PRECISION, CAST(ROUND(ii.StandardCost, 3) AS DECIMAL(19, 3))) AS 'Standard Cost'
FROM Item i
     INNER JOIN ItemInventoryTransaction iit ON i.itempk = iit.itemfk
     INNER JOIN ItemInventoryTransactionType iitt ON iitt.ItemInventoryTransactionTypePK = iit.ItemInventoryTransactionTypeFK
     INNER JOIN ItemInventory ii ON i.ItemInventoryFK = ii.ItemInventoryPK
     INNER JOIN ItemDivision id ON i.ItemPK = id.ItemFK
     INNER JOIN Division d ON id.DivisionFK = d.DivisionPK
WHERE(iitt.Name = 'Invoicing'
      OR iitt.Name = 'Issuing'
      OR (iitt.Name = 'Post Worksheet' AND iit.quantity <= 0))
     AND iit.TransactionDate BETWEEN @StartDate AND @EndDate
     AND id.DivisionFK = @division
     AND iit.DivisionNumber = @division
GROUP BY i.PartNumber,
         id.quantityOnHand,
         ii.StandardCost
UNION
SELECT i.PartNumber AS 'Part Number',
       NULL AS 'Sum Quantity',
       CONVERT(DOUBLE PRECISION, id.quantityOnHand) AS 'Division Quantity on Hand',
       NULL AS 'Avg Use Per Day',
       NULL AS 'Depletion Days per Avg Use',
       CONVERT(DOUBLE PRECISION, CAST(ROUND(ii.StandardCost, 3) AS DECIMAL(19, 3))) AS 'Standard Cost'
FROM Item i
     INNER JOIN ItemInventoryTransaction iit ON i.itempk = iit.itemfk
     INNER JOIN ItemInventoryTransactionType iitt ON iitt.ItemInventoryTransactionTypePK = iit.ItemInventoryTransactionTypeFK
     INNER JOIN ItemInventory ii ON i.ItemInventoryFK = ii.ItemInventoryPK
     INNER JOIN ItemDivision id ON i.ItemPK = id.ItemFK
     INNER JOIN Division d ON id.DivisionFK = d.DivisionPK
WHERE id.DivisionFK = @division
      AND iit.DivisionNumber = @division
ORDER BY [Part Number];

1 个答案:

答案 0 :(得分:0)

执行此操作的简单方法是将WHERE子句添加到第二个查询中,从而反转第一个查询的过滤条件,从而避免单词go重复。

我告诫不要在所有内容中都使用诸如MAX之类的聚合表达式,因为如果两个重复条目中的任何一个对于您选择的任何字段都不相同,这就会使您出现数据不一致的情况,而且由于任何原因它也会变慢并且难以辨认

将WHERE添加到联合的第二个查询中的示例:

WHERE(iitt.Name <> 'Invoicing'
      AND iitt.Name <> 'Issuing'
      AND (iitt.Name <> 'Post Worksheet'
          OR iit.quantity > 0))
     OR iit.TransactionDate NOT BETWEEN @StartDate AND @EndDate
     OR id.DivisionFK <> @division
     OR iit.DivisionNumber <> @division

这是基于De-Morgan Laws of Binary Math

的上述条件反转的结果