0

我正在尝试编写一个查询,该查询返回用户在我的应用程序中创建的每个类别中的事务总和。我当前的查询工作正常,但如果尚未在该类别下进行任何交易,它不会显示该类别。即使所有内容的总和为 0,我也希望我的查询显示每个类别。

我查找了如何做到这一点,并被建议使用 LEFT/RIGHT OUTER JOIN,但它并没有达到我想要的效果。

我正在通过 Windows C# 应用程序访问 Microsoft Access 2007 数据库。这是我当前的查询:

SELECT Categories.CategoryName ,
       SUM( Transactions.TransactionCredit ) as CreditSum ,
       SUM( Transactions.TransactionDebit  ) as DebitSum  ,
       SUM( Transactions.TransactionCredit ) -
       SUM( Transactions.TransactionDebit  ) as Difference ,
       SUM( Transactions.TransactionDebit  ) /
       ( SELECT SUM(TransactionDebit)
         FROM Transactions
         WHERE AccountID = {currentAccountId}
       ) as 'Percent of Total Debit'
FROM Categories
LEFT JOIN Transactions on Categories.CategoryName = Transactions.CategoryName
WHERE Transactions.AccountID = {currentAccountId}
  AND TransactionDate >= {startDate}
  AND TransactionDate <= {endDate}
GROUP BY Categories.CategoryName

这就是它在我的 c# 应用程序中的编码方式:

queries.returnQuery("SELECT Categories.CategoryName, " +
"SUM(Transactions.TransactionCredit) as CreditSum, " +
"SUM(Transactions.TransactionDebit) as DebitSum, " +
"SUM(Transactions.TransactionCredit) - SUM(Transactions.TransactionDebit) as Difference, " +
"SUM(Transactions.TransactionDebit) / (SELECT SUM(TransactionDebit) FROM Transactions WHERE AccountID = " + currentAccountID + ") as 'Percent of Total Debit' " +
"FROM Categories LEFT JOIN Transactions on Categories.CategoryName = Transactions.CategoryName " +
"WHERE Transactions.AccountID = " + currentAccountID +
(enableDateFilter ? " AND Transactions.TransactionDate >= #" + startDate + "# AND Transactions.TransactionDate <= #" + endDate + "# " : " ") +
" GROUP BY Categories.CategoryName");
4

3 回答 3

1

如果没有双引号,您的查询会更容易理解。无论如何,问题在于where子句引用了Transactions表,撤消了left outer join. 将这些条件移到on子句中。在您的情况下,这很容易通过将 to 更改whereand

"SELECT Categories.CategoryName, " +
"SUM(Transactions.TransactionCredit) as CreditSum, " +
"SUM(Transactions.TransactionDebit) as DebitSum, " +
"SUM(Transactions.TransactionCredit) - SUM(Transactions.TransactionDebit) as Difference, " +
"SUM(Transactions.TransactionDebit) / (SELECT SUM(TransactionDebit) FROM Transactions WHERE AccountID = " + currentAccountID + ") as 'Percent of Total Debit' " +
"FROM Categories LEFT JOIN Transactions on Categories.CategoryName = Transactions.CategoryName " +
"and Transactions.AccountID = " + currentAccountID +
(enableDateFilter? " AND TransactionDate >= #" + startDate + "# AND TransactionDate <= #" + endDate + "# " : " ") +
"GROUP BY Categories.CategoryName"
于 2013-09-17T19:47:00.557 回答
0

当您使用LEFT JOINbetween CategoriesandTransactions时,您应该期望NULLTransaction 表上的值。在 JOIN 子句中包含您的 AccountID 过滤器可以解决问题:

DECLARE @currentAccountId INT
SELECT  @currentAccountId = 1

;WITH   Transactions AS
(
    SELECT  *
    FROM    (   
    VALUES
                (1, 1000., 2000., 'Category B'),
                (2, 2000., 1000., 'Category B'),
                (1, 1000., 1000., 'Category C')
            )
            T ( AccountID, TransactionCredit, TransactionDebit, CategoryName)
),      Categories AS
(
    SELECT  *
    FROM    (
    VALUES
                ('Category A'),
                ('Category B'),
                ('Category C')
            )
            C (CategoryName)
)
SELECT      Categories.CategoryName ,
            SUM( Transactions.TransactionCredit ) as CreditSum ,
            SUM( Transactions.TransactionDebit  ) as DebitSum  ,
            SUM( Transactions.TransactionCredit ) -
            SUM( Transactions.TransactionDebit  ) as Difference ,
            SUM( Transactions.TransactionDebit  ) /
            (
                SELECT  SUM(TransactionDebit)
                FROM    Transactions
                WHERE   AccountID = @currentAccountId
            ) AS 'Percent of Total Debit'
FROM        Categories
LEFT JOIN   Transactions
    ON      Categories.CategoryName = Transactions.CategoryName
            AND Transactions.AccountID = @currentAccountId
            --AND TransactionDate >= {startDate}
            --AND TransactionDate <= {endDate}
GROUP BY    Categories.CategoryName

结果

CategoryName    CreditSum   DebitSum    Difference  Percent of Total Debit
---------------------------------------------------------------------------------
Category A      NULL        NULL        NULL        NULL
Category B      1000        2000        -1000       0.666666
Category C      1000        1000        0           0.333333
于 2013-09-17T21:46:38.960 回答
0

我面临的问题是,在使用 JOIN 时,您必须使用将两个表进行比较的条件。就我而言,我没有这样做。我使用的是用户在 c# 应用程序中选择的参数,因此我使用 SUBQUERY 代替 Transactions 表并获得了预期的结果。请参阅下面的解决方案:

C#中的解决方案:

queries.returnQuery("SELECT Categories.CategoryName, " +
                           "SUM(SUBQUERY.TransactionCredit) as CreditSum, " +
                           "SUM(SUBQUERY.TransactionDebit) as DebitSum, " +
                           "SUM(SUBQUERY.TransactionCredit) - SUM(SUBQUERY.TransactionDebit) as Difference " +
                           "FROM Categories LEFT JOIN " +
                               "(SELECT CategoryName, TransactionCredit, TransactionDebit FROM Transactions WHERE AccountID = " + currentAccountID + 
                               (enableDateFilter ? " AND TransactionDate >= #" + startDate + "# AND TransactionDate <= #" + endDate + "# " : " ") + 
                               ") AS SUBQUERY " + 
                           "ON Categories.CategoryName = SUBQUERY.CategoryName " +
                           "GROUP BY Categories.CategoryName");

不在 C# 中的解决方案:

SELECT Categories.CategoryName ,
       SUM( SUBQUERY.TransactionCredit ) as CreditSum ,
       SUM( SUBQUERY.TransactionDebit  ) as DebitSum  ,
       SUM( SUBQUERY.TransactionCredit ) -
       SUM( SUBQUERY.TransactionDebit  ) as Difference ,
       SUM( SUBQUERY.TransactionDebit  ) /
       ( SELECT SUM(TransactionDebit)
         FROM Transactions
         WHERE AccountID = {currentAccountId}
       ) as 'Percent of Total Debit'
FROM Categories
LEFT JOIN 
(
    SELECT CategoryName, 
           TransactionCredit, 
           TransactionDebit 
    FROM Transactions 
    WHERE AccountID = {currentAccountID}
      AND TransactionDate >= {startDate}
      AND TransactionDate <= {endDate}
) as SUBQUERY 
ON Categories.CategoryName = SUBQUERY.CategoryName
GROUP BY Categories.CategoryName
于 2013-09-18T19:41:43.293 回答