查询将循环一系列年份

时间:2016-04-13 21:54:22

标签: sql loops ms-access

我正在寻找让ACCESS查询返回结果多年的方法。由于查询中存在聚合计算,因此将BETWEEN语句更改为年份范围会导致错误。我可以使用UNION语句并重复每年的代码,但这不是非常有效。可以只使用SQL代码完成,还是必须使用VB。我不懂VB,所以如果答案是需要VB,我会很感激详细信息。

ACCESS查询的代码如下:

SELECT DISTINCT
    DatePart("yyyy",sale_date) AS [YEAR],

    (SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0) ,2) 
     FROM SALES_RECEIPT
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009#) AS [Gross Sales],

    (SELECT Round(Nz(Sum((Nz(inventory.VENDOR_ACTUAL_PRICE,0))*sales_receipt.quantity),0),2) 
     FROM SALES_RECEIPT
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009#) AS COGS,

    (SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0) - Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * sales_receipt.quantity),0),2) 
     FROM INVENTORY 
     INNER JOIN SALES_RECEIPT ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009#) AS [Sales Margin],

    Round((((SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0) - Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * sales_receipt.quantity),0),2) 
             FROM INVENTORY 
             INNER JOIN SALES_RECEIPT ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
             WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009# )
             /
            (SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0),2) 
             FROM SALES_RECEIPT
             INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
             WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009#))*100),0) & "%" AS [Profit Margin],

    (SELECT Round(Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * deductions_inventory.quantity), 0),2)
     FROM INVENTORY INNER JOIN DEDUCTIONS_INVENTORY ON INVENTORY.INVENTORY_ID = DEDUCTIONS_INVENTORY.INVENTORY_ID
     WHERE DEDUCTIONS_INVENTORY.ENTRY_DATE Between #1/1/2009# And #12/31/2009# ) AS [Inventory Deductions],

    (SELECT Round(Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * DEDUCTIONS_EXPENSE.quantity), 0),2)
     FROM INVENTORY INNER JOIN DEDUCTIONS_EXPENSE ON INVENTORY.INVENTORY_ID = DEDUCTIONS_EXPENSE.INVENTORY_ID
     WHERE DEDUCTIONS_EXPENSE.ENTRY_DATE Between #1/1/2009# And #12/31/2009# ) AS [Inventory Expenses], 

    (SELECT Round(Nz(Sum(DEDUCTIONS_FIXTURES_CHAINS.VENDOR_ACTUAL_PRICE*DEDUCTIONS_FIXTURES_CHAINS.quantity),0),2) 
     FROM DEDUCTIONS_FIXTURES_CHAINS
     WHERE DEDUCTIONS_FIXTURES_CHAINS.ENTRY_DATE Between #1/1/2009# And #12/31/2009# and REASON="Breakage-Theft") AS [Fixture & Chain Deductions], 

    (SELECT Round(Nz(Sum(DEDUCTIONS_FIXTURES_CHAINS.VENDOR_ACTUAL_PRICE*DEDUCTIONS_FIXTURES_CHAINS.quantity),0),2) 
     FROM DEDUCTIONS_FIXTURES_CHAINS
     WHERE DEDUCTIONS_FIXTURES_CHAINS.ENTRY_DATE Between #1/1/2009# And #12/31/2009# and REASON="Promotion") AS [Fixture & Chain Expenses], 

    (SELECT Round(Nz(Sum(returns.selling_price * returns.quantity), 0),2)
     FROM returns inner JOIN inventory ON INVENTORY.INVENTORY_ID = returns.INVENTORY_ID
     WHERE returns.return_date Between #1/1/2009# And #12/31/2009# ) AS [Sales Returns], 

    (SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0) - Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * sales_receipt.quantity),0),2)
     FROM INVENTORY 
     INNER JOIN SALES_RECEIPT ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] Between #1/1/2009# And #12/31/2009#)
     -
    (SELECT Round(Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * deductions_inventory.quantity), 0),2)
     FROM INVENTORY INNER JOIN DEDUCTIONS_INVENTORY ON INVENTORY.INVENTORY_ID = DEDUCTIONS_INVENTORY.INVENTORY_ID
     WHERE DEDUCTIONS_INVENTORY.ENTRY_DATE Between #1/1/2009# And #12/31/2009#)
     -
    (SELECT Round(Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * DEDUCTIONS_EXPENSE.quantity), 0),2)
     FROM INVENTORY INNER JOIN DEDUCTIONS_EXPENSE ON INVENTORY.INVENTORY_ID = DEDUCTIONS_EXPENSE.INVENTORY_ID
     WHERE DEDUCTIONS_EXPENSE.ENTRY_DATE Between #1/1/2009# And #12/31/2009#)
     -
    (SELECT Round(Nz(Sum(DEDUCTIONS_FIXTURES_CHAINS.VENDOR_ACTUAL_PRICE*DEDUCTIONS_FIXTURES_CHAINS.quantity),0),2) 
     FROM DEDUCTIONS_FIXTURES_CHAINS
     WHERE DEDUCTIONS_FIXTURES_CHAINS.ENTRY_DATE Between #1/1/2009# And #12/31/2009#) 
     -
    (SELECT Nz(Sum(returns.selling_price * returns.quantity), 0)
     FROM returns inner JOIN inventory ON INVENTORY.INVENTORY_ID = returns.INVENTORY_ID
     WHERE returns.return_date Between #1/1/2009# And #12/31/2009#) AS [Gross Profit]

FROM
    INVENTORY
    INNER JOIN SALES_RECEIPT ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
WHERE
    (((SALES_RECEIPT.SAle_date) Between #1/1/2009# And #12/31/2009#))
GROUP BY
    DatePart("yyyy",sale_date);

2 个答案:

答案 0 :(得分:0)

原则上,您需要使用与外部查询相关的条件替换子查询中的所有Between #1/1/2009# And #12/31/2009#条件。
如果按原样执行,您将获得一个完全低效的查询,该查询将计算外部查询中每个单独记录的总计。

在这种情况下,除了为您提供单年编号(2009)之外,您似乎没有使用外部查询。

因此,将外部查询更改为仅返回感兴趣的年份数,并使子查询相关,例如

SELECT
    Year(years.year_start) AS [YEAR],

    (SELECT Round(Nz(Sum(sales_receipt.SELLING_PRICE * sales_receipt.quantity),0) ,2) 
     FROM SALES_RECEIPT
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] between years.year_start and years.year_end) AS [Gross Sales],

    (SELECT Round(Nz(Sum((Nz(inventory.VENDOR_ACTUAL_PRICE,0))*sales_receipt.quantity),0),2) 
     FROM SALES_RECEIPT
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
     WHERE SALES_RECEIPT.[SALE_DATE] between years.year_start and years.year_end) AS COGS,

    etc
FROM
    (select
         DateSerial(Year(sale_date), 1, 1) as year_start,
         DateSerial(Year(sale_date), 12, 31) as year_end
     from SALES_RECEIPT
     where sale_date between #1/1/2009# And #12/31/2015#
     group by Year(sale_date)
    ) as years

答案 1 :(得分:0)

考虑删除外部聚合查询的WHERE子句,该子句筛选2009日期,并使每个子查询与不同的sale_date年份相关。不需要BETWEEN条款,但使用DatePart("yyyy", ...),这将对应SALES_RECIEPT表中的每个不同年份。以下是前三个子查询的调整:

SELECT DISTINCT
    DatePart("yyyy", SALES_RECEIPT.sale_date) AS [YEAR],

    (SELECT Round(Nz(Sum(sub1.SELLING_PRICE * sub1.quantity),0) ,2) 
     FROM SALES_RECEIPT AS sub1
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = sub1.INVENTORY_ID
     WHERE DatePart("yyyy", sub1.[SALE_DATE]) =  
           DatePart("yyyy", SALES_RECEIPT.sale_date)) As [Gross Sales],

    (SELECT Round(Nz(Sum((Nz(inventory.VENDOR_ACTUAL_PRICE,0)) * sub2.quantity),0),2) 
     FROM SALES_RECEIPT As sub2
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = sub2.INVENTORY_ID
     WHERE DatePart("yyyy", sub2.SALES_RECEIPT.[SALE_DATE]) = 
           DatePart("yyyy", SALES_RECEIPT.sale_date)) AS COGS,

    (SELECT Round(Nz(Sum(sub3.SELLING_PRICE * sub3.quantity),0) - 
            Nz(Sum(inventory.VENDOR_ACTUAL_PRICE * sub3.quantity),0),2) 
     FROM SALES_RECEIPT As sub3
     INNER JOIN INVENTORY ON INVENTORY.INVENTORY_ID = sub3.INVENTORY_ID
     WHERE DatePart("yyyy", sub3.sale_date) =  
           DatePart("yyyy", SALES_RECEIPT.[SALE_DATE])) AS [Sales Margin],

    ...

FROM
    INVENTORY
    INNER JOIN SALES_RECEIPT ON INVENTORY.INVENTORY_ID = SALES_RECEIPT.INVENTORY_ID
GROUP BY
    DatePart("yyyy", SALES_RECEIPT.sale_date);