我在Access和SQL编程方面相当新。我正在尝试执行以下操作:
Sum(SO_SalesOrderPaymentHistoryLineT.Amount) AS [Sum Of PaymentPerYear]
并且即使在某些年份没有金额的情况下也会逐年分组。我希望将这些年份列为包含图表的报告。我不确定这是否可行,但我们非常感谢你的每一点帮助。
到目前为止我的代码如下:
SELECT
Base_CustomerT.SalesRep,
SO_SalesOrderT.CustomerId,
Base_CustomerT.Customer,
SO_SalesOrderPaymentHistoryLineT.DatePaid,
Sum(SO_SalesOrderPaymentHistoryLineT.Amount) AS [Sum Of PaymentPerYear]
FROM
Base_CustomerT
INNER JOIN (
SO_SalesOrderPaymentHistoryLineT
INNER JOIN SO_SalesOrderT
ON SO_SalesOrderPaymentHistoryLineT.SalesOrderId = SO_SalesOrderT.SalesOrderId
) ON Base_CustomerT.CustomerId = SO_SalesOrderT.CustomerId
GROUP BY
Base_CustomerT.SalesRep,
SO_SalesOrderT.CustomerId,
Base_CustomerT.Customer,
SO_SalesOrderPaymentHistoryLineT.DatePaid,
SO_SalesOrderPaymentHistoryLineT.PaymentType,
Base_CustomerT.IsActive
HAVING
(((SO_SalesOrderPaymentHistoryLineT.PaymentType)=1)
AND ((Base_CustomerT.IsActive)=Yes))
ORDER BY
Base_CustomerT.SalesRep,
Base_CustomerT.Customer;
答案 0 :(得分:0)
您需要列出所有年份的另一个表 - 您可以动态创建此表,或者在数据库中添加一个...从中加入。因此,如果您有一个名为alltheyears的表,其中一个名为y的列刚刚列出了年份,那么您可以使用这样的代码:
WITH minmax as
(
select min(year(SO_SalesOrderPaymentHistoryLineT.DatePaid) as minyear,
max(year(SO_SalesOrderPaymentHistoryLineT.DatePaid) as maxyear)
from SalesOrderPaymentHistoryLineT
), yearsused as
(
select y
from alltheyears, minmax
where alltheyears.y >= minyear and alltheyears.y <= maxyear
)
select *
from yearsused
join ( -- your query above goes here! -- ) T
ON year(T.SO_SalesOrderPaymentHistoryLineT.DatePaid) = yearsused.y
答案 1 :(得分:0)
您需要一个提供年份数字的数据源。你不能凭空制造它们。假设您有一个表Interesting_year
,其中包含一列year
,例如填充了2000到2050之间的每个不同整数,您可以执行以下操作:
SELECT
base.SalesRep,
base.CustomerId,
base.Customer,
base.year,
Sum(NZ(data.Amount)) AS [Sum Of PaymentPerYear]
FROM
(SELECT * FROM Base_CustomerT INNER JOIN Year) AS base
LEFT JOIN
(SELECT * FROM
SO_SalesOrderT
INNER JOIN SO_SalesOrderPaymentHistoryLineT
ON (SO_SalesOrderPaymentHistoryLineT.SalesOrderId = SO_SalesOrderT.SalesOrderId)
) AS data
ON ((base.CustomerId = data.CustomerId)
AND (base.year = Year(data.DatePaid))),
WHERE
(data.PaymentType = 1)
AND (base.IsActive = Yes)
AND (base.year BETWEEN
(SELECT Min(year(DatePaid) FROM SO_SalesOrderPaymentHistoryLineT)
AND (SELECT Max(year(DatePaid) FROM SO_SalesOrderPaymentHistoryLineT))
GROUP BY
base.SalesRep,
base.CustomerId,
base.Customer,
base.year,
ORDER BY
base.SalesRep,
base.Customer;
请注意以下事项:
BaseCustomerT
与Interesting_year
的笛卡尔积,以便将基本客户数据与每年相关联(有时称为CROSS JOIN
,但它为&#39} ; s与没有连接谓词的INNER JOIN
相同,这是Access要求的)LEFT JOIN
)。如果(基本客户,年份)组合没有关联订单,则联接结果的其余列将为NULL
。NULL
中选择了SO_SalesOrderT
,则有时会获得Nz()
NULL
功能将HAVING
付款金额转换为0(与未付款的年份对应的行)WHERE
子句转换为WHERE
子句。在这种特定情况下,它在语义上是等效的,并且它会更高效,因为{<1}}过滤器在组形成之前应用,并且因为它允许从某些列中省略某些列GROUP BY
条款。Intersting_year
仅包含您想要结果的年份数字,您可以在没有该过滤条件及其子查询的情况下实现相同的效果。更新:将查询修改为不同的,但逻辑上相同的&#34;类似这样的&#34;我希望Access会更好。除了添加一堆括号外,主要区别在于将LEFT JOIN
的左右操作数都放入子查询中。这与解决Access&#34;模糊外连接的共识建议一致&#34;错误。
答案 2 :(得分:0)
感谢John的帮助。我找到了一个适合我的解决方案。它看起来很安静,但我从中学到了很多东西。如果您对此感兴趣,请立即了解它。
SELECT DISTINCTROW
Base_Customer_RevenueYearQ.SalesRep,
Base_Customer_RevenueYearQ.CustomerId,
Base_Customer_RevenueYearQ.Customer,
Base_Customer_RevenueYearQ.RevenueYear,
CustomerPaymentPerYearQ.[Sum Of PaymentPerYear]
FROM
Base_Customer_RevenueYearQ
LEFT JOIN CustomerPaymentPerYearQ
ON (Base_Customer_RevenueYearQ.RevenueYear = CustomerPaymentPerYearQ.[RevenueYear])
AND (Base_Customer_RevenueYearQ.CustomerId = CustomerPaymentPerYearQ.CustomerId)
GROUP BY
Base_Customer_RevenueYearQ.SalesRep,
Base_Customer_RevenueYearQ.CustomerId,
Base_Customer_RevenueYearQ.Customer,
Base_Customer_RevenueYearQ.RevenueYear,
CustomerPaymentPerYearQ.[Sum Of PaymentPerYear]
;