过去几天,我在SO用户中获得了一些极好的帮助,他们对SQL的了解显然远远超出了我的能力。现在,我可以再次向那些比我更有知识的人提供一些建议。这个问题主要来自here。
我已经调整了原始查询以满足要求,现在看起来像这样:
DECLARE @startDate date = '2015-01-05',
@endDate date = '2015-06-05',
@tempDeduction decimal(10, 4) = NULL
SELECT (SELECT
ContactId AS '@ContactId',
VesselOwner AS '@Owner',
Owed AS '@Owed',
WeeklyDeductionRate AS '@WeeklyDeductionRate',
FromMinimumReturn AS '@FromMinimumReturn',
DeductionRate AS '@DeductionRate',
TotalDeductions AS '@TotalDeductions',
TotalToBeReturned AS '@TotalToBeReturned',
InternalCommission AS '@InternalCommissionRate',
InternalDeduction AS '@InternalDeductionRate',
(SELECT DISTINCT
ld1.ProductId AS '@ProductId',
FORMAT(AVG(ld1.UnitPrice), 'N2') AS '@Cost',
FORMAT(SUM(ld1.Quantity), 'N2') AS '@Quantity'
FROM LandingDetails ld1
INNER JOIN dbo.LandingHeaders lh1
ON ld1.LandingId = lh1.LandingId
WHERE Posted = 0
AND lh1.VesselOwner = a.VesselOwner
GROUP BY ld1.ProductId
FOR xml PATH ('Products'), TYPE)
FROM (SELECT
Contacts.ContactId AS ContactId,
LandingHeaders.VesselOwner AS VesselOwner,
FORMAT(SUM(LandingDetails.Quantity * LandingDetails.UnitPrice), 'N2') AS Owed,
SocietyMemberships.WeeklyDeductionRate AS WeeklyDeductionRate,
SocietyMemberships.FromMinimumReturn AS FromMinimumReturn,
Deductions.DeductionRate,
Vessels.InternalCommission AS InternalCommissionRate,
Vessels.InternalDeduction AS InternalDeductionRate,
FORMAT(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END, 'N2') AS TotalDeductions,
--need to add some logic here I presume that utiles the sql below that is being used to calculate the total to be returned
FORMAT(SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END), 'N2') AS TotalToBeReturned
FROM dbo.LandingDetails
INNER JOIN dbo.LandingHeaders
ON LandingDetails.LandingId = LandingHeaders.LandingId
INNER JOIN dbo.Vessels
ON LandingHeaders.VesselId = Vessels.VesselId
INNER JOIN dbo.Contacts
ON Vessels.OwnerId = Contacts.ContactId
INNER JOIN dbo.SocietyMemberships
ON Contacts.SocietyId = SocietyMemberships.SocietyId
INNER JOIN dbo.Deductions
ON Vessels.DeductionId = Deductions.DeductionId
WHERE LandingHeaders.Posted = 0
AND LandingDate1 BETWEEN @startDate AND @endDate
GROUP BY ContactId,
LandingHeaders.VesselOwner,
SocietyMemberships.WeeklyDeductionRate,
SocietyMemberships.FromMinimumReturn,
Deductions.DeductionRate) a
ORDER BY ContactId
FOR xml PATH ('Owner'), TYPE)
FOR xml PATH ('PurchaseOrders'), TYPE
我添加了逻辑,这样xml也会显示最终的金额((一旦扣除已经从已欠款中删除)将被返回(除了由于舍入误差导致奇数记录偶尔出现1便士差异)货币数据类型)它可以按照我的意愿运作。
我现在正试图建立实现最后一小块逻辑的最佳方法。第一个select语句中有两个新列:InternalCommission和InternalDeduction。这些实际上是互斥的(换句话说,如果一个包含大于0的值,另一个将为0),它们用于计算要添加或扣除的金额(当前为TotalToBeReturned的百分比)。目标是最终得到xmlattributes,显示在通信或扣除中支付或扣除的金额,并调整TotalToBeReturned以反映这些新要求。
我的感觉是我需要将创建TotalToBeReturned的部分分配给一个临时值(作为@tempDeduction添加到sql的顶部,然后使用它来执行必要的逻辑。但是如果我尝试的话在我在sql编译器不喜欢的查询中添加注释的地方下面设置该变量。
我的推理是否正确,如果是这样,我应该如何设置该变量并使用它来应用业务逻辑?
由于
答案 0 :(得分:0)
万一有人应该偶然发现这一点,并希望看到解决方案。最重要的是,在执行逻辑时,绝对有必要引用实际的基础表名而不是别名。最后,以下工作。
该语言被故意设置为英式英语,因为我想在结果xml中使用£符号。 sqlserver常常以美国英语为默认值。
SET LANGUAGE 'British English'
DECLARE @startDate date ,
@endDate date
SELECT (SELECT
ContactId AS '@ContactId',
VesselOwner AS '@Owner',
FORMAT(Owed, 'N2') AS '@Owed',
FORMAT(WeeklyDeductionRate, 'C') AS '@WeeklyDeductionRate',
FORMAT(FromMinimumReturn, 'C') AS '@FromMinimumReturn',
FORMAT(DeductionRate, 'P') AS '@DeductionRate',
FORMAT(TotalDeductions, 'N2') AS '@TotalDeductions',
Format(TempReturn, 'N2') AS '@TempReturn',
FORMAT(InternalCommission, 'P') AS '@InternalCommissionRate',
FORMAT(InternalDeduction, 'P') AS '@InternalDeductionRate',
FORMAT(InternalCommissionAmount, 'N2') AS '@InternalCommissionAmount',
FORMAT(InternalDeductionAmount, 'N2') AS '@InternalDeductionAmount',
FORMAT(TotalToBeReturned, 'N2') AS '@TotalToBeReturned',
(SELECT DISTINCT
ld1.ProductId AS '@ProductId',
FORMAT(AVG(ld1.UnitPrice), 'N2') AS '@Cost',
FORMAT(SUM(ld1.Quantity), 'N2') AS '@Quantity'
FROM LandingDetails ld1
INNER JOIN dbo.LandingHeaders lh1
ON ld1.LandingId = lh1.LandingId
WHERE Posted = 0
AND lh1.VesselOwner = a.VesselOwner
GROUP BY ld1.ProductId
FOR xml PATH ('Products'), TYPE)
FROM (SELECT
Contacts.ContactId AS ContactId,
LandingHeaders.VesselOwner AS VesselOwner,
SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) AS Owed,
SocietyMemberships.WeeklyDeductionRate AS WeeklyDeductionRate,
SocietyMemberships.FromMinimumReturn AS FromMinimumReturn,
Deductions.DeductionRate,
Vessels.InternalCommission,
Vessels.InternalDeduction,
CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END AS TotalDeductions,
SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END) AS TempReturn,
(SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) * InternalCommission AS InternalCommissionAmount,
(SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) * InternalDeduction AS InternalDeductionAmount,
CASE
WHEN (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) * InternalCommission > 0 THEN (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) + ((SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) * InternalCommission)
ELSE (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) + ((SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) -
(CASE
WHEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) - (SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate) > FromMinimumReturn THEN SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate + WeeklyDeductionRate
ELSE SUM(LandingDetails.Quantity * LandingDetails.UnitPrice) * DeductionRate
END)) * InternalDeduction)
END AS TotalToBeReturned
FROM dbo.LandingDetails
INNER JOIN dbo.LandingHeaders
ON LandingDetails.LandingId = LandingHeaders.LandingId
INNER JOIN dbo.Vessels
ON LandingHeaders.VesselId = Vessels.VesselId
INNER JOIN dbo.Contacts
ON Vessels.OwnerId = Contacts.ContactId
INNER JOIN dbo.SocietyMemberships
ON Contacts.SocietyId = SocietyMemberships.SocietyId
INNER JOIN dbo.Deductions
ON Vessels.DeductionId = Deductions.DeductionId
WHERE LandingHeaders.Posted = 0
AND LandingDate1 BETWEEN @startDate AND @endDate
GROUP BY ContactId,
LandingHeaders.VesselOwner,
SocietyMemberships.WeeklyDeductionRate,
SocietyMemberships.FromMinimumReturn,
Deductions.DeductionRate,
Vessels.InternalCommission,
Vessels.InternalDeduction) a
ORDER BY ContactId
FOR xml PATH ('Owner'), TYPE)
FOR xml PATH ('PurchaseOrders'), TYPE