【发布时间】:2018-12-06 17:00:35
【问题描述】:
我正在写一个查询。它从几个不同的表中收集一些数据,并运行一个总和和一些平均值。 最初,我的客户要求我根据某些标准进行选择,限制在整个零件列表中,但是,现在客户希望能够显示所有项目,即使它们不符合标准。 我遇到的问题是我的初始查询显然限制了选择,因为它需要使用 where 子句来决定某些条件(例如,基于类别,它仅在结果为负时包含结果,但在正时不包含结果)和在尝试使用联合时,只要某些东西确实符合标准,我就会得到一个重复的条目。意思是,我的第二个 Select 得到了所有内容,但是当它已经从第一个添加时,它并没有过滤掉该条目。 Union 不认为这些是不同的,因为计算的字段是不同的,即使部件号是匹配的。
我尝试创建一组反向条件,这些条件将简单地获得初始选择的镜像,从而消除任何重复的可能性,但是,我找不到正确的标准。
我是否可以帮助为以下一组 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];
【问题讨论】:
-
默认情况下
UNION表示UNION DISTINCT,因此它应该自行删除所有重复项。但所有列都必须相同,否则它们并不是真正的重复。 -
请参阅 De Morgan's laws 了解如何反转
AND和OR条件的组合。 -
反转条件不是像
WHERE NOT (condition)这么简单吗? -
我找到了方法。首先,使联合选择一个With,然后为每个值选择最大值,它将删除重复的行。 With Usage As (...) SELECT MAX([part number]), MAX([Sum Quantity]), MAX([Division Quantity on Hand]), MAX([Avg Use Per Day]), MAX([Depletion Days] per Avg Use]), MAX([Standard Cost]) FROM Usage GROUP BY [part number];
标签: sql tsql duplicates union