使用Access在SQL中按年份进行并行数据比较

使用Access在SQL中按年份进行并行数据比较,sql,ms-access,parameters,comparison,pivot,Sql,Ms Access,Parameters,Comparison,Pivot,我需要每年对数据进行一次并排比较 我正在使用Microsoft Access 2013 我想要得到的是这样一张表: ╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗ ║ Zone ║ Customer ║ ... ║ Month ║ Previous year ║ Current year ║ Difference ║ ╠══════╬══════════╬ ... ╬═══════╬═══

我需要每年对数据进行一次并排比较

我正在使用Microsoft Access 2013

我想要得到的是这样一张表:

╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗
║ Zone ║ Customer ║ ... ║ Month ║ Previous year ║ Current year ║ Difference ║
╠══════╬══════════╬ ... ╬═══════╬═══════════════╬══════════════╬════════════╣
║ PD   ║ A        ║ ... ║     1 ║ 100€          ║ 150€         ║ +50€       ║
║ PD   ║ B        ║ ... ║     2 ║ 150€          ║ 100€         ║ -50€       ║
║ PD   ║ C        ║ ... ║     1 ║ 200€          ║ 0€           ║ -200€      ║
║ PD   ║ D        ║ ... ║     2 ║ 0€            ║ 100€         ║ +100€      ║
╚══════╩══════════╩ ... ╩═══════╩═══════════════╩══════════════╩════════════╝

("..." stands for other columns)
SELECT 
    Customer, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS LastYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) AS ThisYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) 
       - Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS Diff
FROM 
    Invoices
GROUP BY 
    Customer;
PARAMETERS P0 TEXT(255), P1 TEXT(255), P2 TEXT(255), P3 TEXT(255);
SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (@P0, @P1) AND S.MONTH BETWEEN @P2 AND @P3;
确定上一年为2014年,当前为2015年,通过此表,我可以看出:

  • 2014年的一位客户在2015年购买了更多(客户a)
  • 2014年的客户在2015年购买的少于(客户B)
  • 2014年客户尚未在2015年购买(客户C)
  • 2015年有一个新客户(客户D)
当我有一个“老”(2014)客户在2015年没有购买时,我需要在本年度列(2015年)中看到该行的值为“0欧元”,因此对于一个2015年的新客户来说,这一行显然在2014年没有购买任何东西

这些是我的桌子:

  • 客户(id、公司名称、id区、id客户类别)
  • 客户类别(id、说明)
  • 订单(id、id\u客户、日期、数量、金额(€)、id\u产品\u类别、, id(输入)
  • 产品类别(id、供应商、说明)
  • 分区(id、城市)
  • 进口(id、年、月、供应商)
我创建了一个视图(V\u YEAR\u SALES):

每次我需要在一年和上一年之间进行比较时,我都会使用此视图(V_SALES_comparison)通过一年:

SELECT S1.ID_ZONE, S1.CITY, S1.ID_CUSTOMER, S1.CUSTOMER, S1.ID_CUSTOMER_CATEGORY, S1.CUSTOMER_CATEGORY, S1.SUPPLIER, S1.ID_PRODUCT_CATEGORY, S1.PRODUCT_CATEGORY, S1.YEAR, S1.MONTH, S1.AMOUNT AS CURRENT_YEAR, S2.AMOUNT AS PREVIOUS_YEAR, S1.AMOUNT - S2.AMOUNT AS DIFFERENCE
FROM 
    (SELECT * FROM V_YEAR_SALES) AS S1 
    LEFT JOIN 
    (SELECT * FROM V_YEAR_SALES) AS S2 
        ON (S1.ID_ZONE = S2.ID_ZONE) 
        AND (S1.SUPPLIER = S2.SUPPLIER) 
        AND (S1.ID_PRODUCT_CATEGORY = S2.ID_PRODUCT_CATEGORY) 
        AND (S1.ID_CUSTOMER_CATEGORY = S2.ID_CUSTOMER_CATEGORY) 
        AND (S1.ID_CUSTOMER = S2.ID_CUSTOMER) 
        AND (S1.YEAR = S2.YEAR + 1) 
        AND (S1.MONTH = S2.MONTH);
参考上面的期望结果表,使用此视图,我只能获得客户A、B、D的行,而不能获得客户C的行

我需要包括2014年那些2015年还没有购买的客户

我正在使用JOIN,但我不知道这是否是最好的方法。也许我可以使用数据透视,但我不知道是否以及如何使用Access实现数据透视。

您可以这样做:

╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗
║ Zone ║ Customer ║ ... ║ Month ║ Previous year ║ Current year ║ Difference ║
╠══════╬══════════╬ ... ╬═══════╬═══════════════╬══════════════╬════════════╣
║ PD   ║ A        ║ ... ║     1 ║ 100€          ║ 150€         ║ +50€       ║
║ PD   ║ B        ║ ... ║     2 ║ 150€          ║ 100€         ║ -50€       ║
║ PD   ║ C        ║ ... ║     1 ║ 200€          ║ 0€           ║ -200€      ║
║ PD   ║ D        ║ ... ║     2 ║ 0€            ║ 100€         ║ +100€      ║
╚══════╩══════════╩ ... ╩═══════╩═══════════════╩══════════════╩════════════╝

("..." stands for other columns)
SELECT 
    Customer, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS LastYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) AS ThisYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) 
       - Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS Diff
FROM 
    Invoices
GROUP BY 
    Customer;
PARAMETERS P0 TEXT(255), P1 TEXT(255), P2 TEXT(255), P3 TEXT(255);
SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (@P0, @P1) AND S.MONTH BETWEEN @P2 AND @P3;
我发现您有一个单独的年份字段,因此请尝试以下方法:

SELECT 
    Customer, 
    Sum(IIf(Year(Date())-[YearField]=1,[Amount],0)) AS LastYear, 
    Sum(IIf(Year(Date())-[YearField]=0,[Amount],0)) AS ThisYear, 
    Sum(IIf(Year(Date())-[YearField]=0,[Amount],0)) 
       - Sum(IIf(Year(Date())-[YearField]=1,[Amount],0)) AS Diff
FROM 
    Invoices
GROUP BY 
    Customer;

最后,我使用旋转找到了解决方案

V_YEAR_SALES视图替换为以下内容:

TRANSFORM
IIF(SUM(O.AMOUNT) IS NULL, 0, SUM(O.AMOUNT))
SELECT Z.ID AS ID_ZONE, Z.CITY, C.COMPANY_NAME AS CUSTOMER, CAT.DESCRIPTION AS CUSTOMER_CATEGORY, P.SUPPLIER, P.DESCRIPTION AS PRODUCT_CATEGORY, I.MONTH, I.YEAR
FROM ((((ORDERS AS O 
    INNER JOIN CUSTOMERS AS C ON O.ID_CUSTOMER = C.ID) 
    INNER JOIN ZONES AS Z ON Z.ID = C.ID_ZONE) 
    INNER JOIN IMPORTS AS I ON I.ID = O.ID_IMPORT) 
    INNER JOIN CUSTOMER_CATEGORIES AS CAT ON CAT.ID = C.ID_CUSTOMER_CATEGORY)
    INNER JOIN PRODUCT_CATEGORIES AS P ON O.ID_PRODUCT_CATEGORY = P.ID
WHERE I.YEAR BETWEEN 
    (SELECT MAX(YEAR) FROM IMPORTS) AND (SELECT MAX(YEAR)-3 FROM IMPORTS)
GROUP BY Z.ID, Z.CITY, C.COMPANY_NAME, CAT.DESCRIPTION, P.SUPPLIER, P.DESCRIPTION, I.MONTH, I.YEAR
V\u SALES\u COMPARISON
视图已删除,因为不再需要该视图。我的查询现在仅适用于
V\u YEAR\u SALES

查询新的
V_年销售
也比
V_年销售

如果需要从Access或无参数查询视图:

SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (2015, 2014) AND S.MONTH BETWEEN 1 AND 12;
相反,如果需要使用Jet Driver从代码中查询视图,并且还希望使用参数,则需要执行以下操作:

╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗
║ Zone ║ Customer ║ ... ║ Month ║ Previous year ║ Current year ║ Difference ║
╠══════╬══════════╬ ... ╬═══════╬═══════════════╬══════════════╬════════════╣
║ PD   ║ A        ║ ... ║     1 ║ 100€          ║ 150€         ║ +50€       ║
║ PD   ║ B        ║ ... ║     2 ║ 150€          ║ 100€         ║ -50€       ║
║ PD   ║ C        ║ ... ║     1 ║ 200€          ║ 0€           ║ -200€      ║
║ PD   ║ D        ║ ... ║     2 ║ 0€            ║ 100€         ║ +100€      ║
╚══════╩══════════╩ ... ╩═══════╩═══════════════╩══════════════╩════════════╝

("..." stands for other columns)
SELECT 
    Customer, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS LastYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) AS ThisYear, 
    Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=0,[Amount],0)) 
       - Sum(IIf(DateDiff("yyyy",[InvoiceDate],Date())=1,[Amount],0)) AS Diff
FROM 
    Invoices
GROUP BY 
    Customer;
PARAMETERS P0 TEXT(255), P1 TEXT(255), P2 TEXT(255), P3 TEXT(255);
SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (@P0, @P1) AND S.MONTH BETWEEN @P2 AND @P3;
小心
选择
语句之前包含
参数
声明(同时使用
),否则您会从Jet Driver得到错误:

The Microsoft Jet database engine does not recognize '[P0]' as a valid field name or expression.

我觉得这是因为这一行:
和(S1.YEAR=S2.YEAR+1)
。。试着做一个
或者(S1.YEAR=S2.YEAR)
。。?这只是一个机会dark@Invent-动画:不,这样我每年/每月/订单只获得许多重复行:[上一年]=100€(左右),[当前年]=100€(左右),[差异]=0€。我试图用我的表实现您的代码,但我只得到一个客户列表,每个总和列为0欧元。你能不能用我的表格做一个有效的查询,或者用更多的细节来解释你的例子?参见修改后的代码。它将匹配年份的金额相加。没有差异,每列始终为0欧元。无论如何,我需要一个基于我必须连接到一起的所有数据的查询。然后发生了其他事情,或者您的数据与您的描述不同。代码在这里经过测试和验证。我不使用
订单
表的
日期
字段来获取年份。相反,我需要使用
IMPORTS
表中的
year
month
字段。因此,我需要在
订单
导入
之间至少执行一个
连接
操作。然后必须从
CUSTOMERS
表中提取
company\u name
(或customer)字段,再次需要另一个
JOIN
。因此,以代码“原样”无法处理我的表,然后我不得不重新排列它。但我没有结果。