使用 Access 在 SQL 中逐年并排比较数据
Side by side data comparison by year in SQL with Access
我需要按年份对数据进行并排比较。
我使用的是 Microsoft Access 2013。
我想要得到的是一个table这样的:
╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗
║ 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)
确定上一年是2014年,今年是2015年,有了这个table我可以看看:
- 一位 2014 年的客户在 2015 年购买了 更多(客户 A);
- 一位 2014 年的客户在 2015 年购买了 less(客户 B);
- 一位 2014 年的客户 尚未购买 2015 年(客户 C);
- 有一个 2015 年的新客户(客户 D)。
当我有一个 "old" (2014) 客户在 2015 年没有购买时 我需要在 Current 中看到价值为“0€”的那一行年列 (2015) 和 2015 年的新客户一样,显然在 2014 年没有购买任何东西。
这些是我的 table:
- CUSTOMERS (id, company_name, id_zone, id_customer_category)
- CUSTOMER_CATEGORIES (id, description)
- 订单(id,id_customer,日期,数量,金额(€),id_product_category,
id_import)
- PRODUCT_CATEGORIES(id、供应商、描述)
- ZONES (id, city)
- IMPORTS(id、年、月、供应商)
我创建了一个视图(V_YEAR_SALES):
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, SUM(O.AMOUNT) AS AMOUNT
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
GROUP BY Z.ID, Z.CITY, C.COMPANY_NAME, CAT.DESCRIPTION, P.SUPPLIER, P.DESCRIPTION, I.MONTH, I.YEAR
ORDER BY Z.CITY, P.SUPPLIER, P.DESCRIPTION, CAT.DESCRIPTION, C.COMPANY_NAME, I.YEAR, I.MONTH;
每次我需要在一年和前一年之间进行比较时,我都会使用这个视图(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);
参照上述想要的结果table,使用这个视图我只能获取客户A、B、D的行但是不是 C!
我需要包括 2015 年尚未购买的 2014 年客户!
我正在使用 JOIN,但我不知道这是否是最佳方法。也许我可以使用 PIVOTING,但我不知道是否以及如何使用 Access 实现。
你可以这样走:
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;
我看到你有一个单独的年份字段,所以试试这个方法:
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;
最后我找到了使用 PIVOTING 的解决方案。
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_SALES_COMPARISON
视图已删除,因为不再需要。我的查询现在仅适用于 V_YEAR_SALES
.
查询新 V_YEAR_SALES
也比 V_SALES_COMPARISON
快。
如果需要从Access或不带参数查询视图:
SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (2015, 2014) AND S.MONTH BETWEEN 1 AND 12;
相反,如果您需要使用 Jet Driver 从代码中查询视图并且您还想使用参数,则需要这样做:
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;
小心 包含 PARAMETERS
声明(在 SELECT
语句之前也包含 ;
),否则 Jet Driver 会出错:
The Microsoft Jet database engine does not recognize '[P0]' as a valid field name or expression.
我需要按年份对数据进行并排比较。
我使用的是 Microsoft Access 2013。
我想要得到的是一个table这样的:
╔══════╦══════════╦ ... ╦═══════╦═══════════════╦══════════════╦════════════╗
║ 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)
确定上一年是2014年,今年是2015年,有了这个table我可以看看:
- 一位 2014 年的客户在 2015 年购买了 更多(客户 A);
- 一位 2014 年的客户在 2015 年购买了 less(客户 B);
- 一位 2014 年的客户 尚未购买 2015 年(客户 C);
- 有一个 2015 年的新客户(客户 D)。
当我有一个 "old" (2014) 客户在 2015 年没有购买时 我需要在 Current 中看到价值为“0€”的那一行年列 (2015) 和 2015 年的新客户一样,显然在 2014 年没有购买任何东西。
这些是我的 table:
- CUSTOMERS (id, company_name, id_zone, id_customer_category)
- CUSTOMER_CATEGORIES (id, description)
- 订单(id,id_customer,日期,数量,金额(€),id_product_category, id_import)
- PRODUCT_CATEGORIES(id、供应商、描述)
- ZONES (id, city)
- IMPORTS(id、年、月、供应商)
我创建了一个视图(V_YEAR_SALES):
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, SUM(O.AMOUNT) AS AMOUNT
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
GROUP BY Z.ID, Z.CITY, C.COMPANY_NAME, CAT.DESCRIPTION, P.SUPPLIER, P.DESCRIPTION, I.MONTH, I.YEAR
ORDER BY Z.CITY, P.SUPPLIER, P.DESCRIPTION, CAT.DESCRIPTION, C.COMPANY_NAME, I.YEAR, I.MONTH;
每次我需要在一年和前一年之间进行比较时,我都会使用这个视图(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);
参照上述想要的结果table,使用这个视图我只能获取客户A、B、D的行但是不是 C!
我需要包括 2015 年尚未购买的 2014 年客户!
我正在使用 JOIN,但我不知道这是否是最佳方法。也许我可以使用 PIVOTING,但我不知道是否以及如何使用 Access 实现。
你可以这样走:
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;
我看到你有一个单独的年份字段,所以试试这个方法:
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;
最后我找到了使用 PIVOTING 的解决方案。
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_SALES_COMPARISON
视图已删除,因为不再需要。我的查询现在仅适用于 V_YEAR_SALES
.
查询新 V_YEAR_SALES
也比 V_SALES_COMPARISON
快。
如果需要从Access或不带参数查询视图:
SELECT S.*
FROM V_YEAR_SALES AS S
WHERE S.YEAR IN (2015, 2014) AND S.MONTH BETWEEN 1 AND 12;
相反,如果您需要使用 Jet Driver 从代码中查询视图并且您还想使用参数,则需要这样做:
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;
小心 包含 PARAMETERS
声明(在 SELECT
语句之前也包含 ;
),否则 Jet Driver 会出错:
The Microsoft Jet database engine does not recognize '[P0]' as a valid field name or expression.