我尝试根据日期间隔比较Access 2010数据库中的数据。示例I包含来自各种采购订单的项目,并且我希望保留这些项目交付到仓库的历史记录。因此,我的采购订单要求数量为10的材料,并且可以在许多交货中部分交货,我想知道这种交货在日期间隔中如何变化。要填写日期字段,使用的条件如下:如果项目在QtyPending字段中有更新,我复制当前行以booelan字段停用它,创建一个新条目,当前更新日期更新QtyPending字段,所以活动记录是项目的实际状态。所以我有一个表格,其中包含有关这些项目的信息,如
PO POItem QtyPending Date Active 4500000123 10 10 01/09/2014 FALSE 4500000123 10 8 05/09/2014 TRUE 4500000122 30 5 03/09/2014 FALSE 4500000122 30 1 04/09/2014 TRUE
在这个例子中,对于第一个项目,这意味着从01/09到04/09,QtyPending字段没有变化,这意味着供应商没有&#39 ; t交付给我,但从01/09到05/08,他给了我一个2的材料。对于第二个,从03/09到04/09,供应商向我提供了4个材料的数量。所以,如果我要从2014年9月2日到2014年9月4日进行报告查询,预期输出是这样的:
PO POItem QtyDelivered 4500000123 10 0 4500000122 30 4
2014年8月31日至2014年9月10日的报告将有此输出
PO POItem QtyDelivered 4500000123 10 2 4500000122 30 4
我没有提出查询来制作此报告。任何人都可以帮助我吗?
答案 0 :(得分:0)
有很多方法可以解决这个问题。最简单的方法是简单地查询两个日期之间的所有必要记录,循环它们并将结果插入临时表中。然后,此临时表可以作为报告的来源。很多人会因为没有使用大型查询而尖叫你,但以最快最简单的方式获得你想要的结果应该是你的首要任务。
您的架构问题在于您没有为每条记录存储QtyDelivered。如果你愿意的话,总结它以获得所需的结果将是一件容易的事。通过不存储此值,您已将一个简单快速的查询转换为更难和更慢的查询,因为您需要以某种方式重新计算此值,并且您必须这样做而不要忘记它可能的事实有两个以上的记录。
要计算此值,您可以使用子查询从上一行检索值,也可以使用左连接执行相同的操作。获得此值后,您可以减去这两个值以获得所需的差异;如果没有前一行,则允许Null值的可能性。获得这些值后,您现在可以对它们求和以获得Group By的最终结果。请注意,为了执行这些计算,您需要有一个或两个级别的子查询。第一个查询应该是:
Select PO, POItem, QtyPending, (Select Top 1 QtyPending from MyTable T2 where T1.PO = T2.PO and T2.Date < T1.Date And (T2.Date between @Date1 and @Date2) Order by T2.Date Desc) as QtyPending2 from MyTable T1 Where T1.Date between @Date1 and @Date2) ...
将其作为另一个子查询或视图,然后可以通过比较QtyPending和QtyPending2的值来计算所需的差异。不要忘记QtyPendin2可能是空的。剩下的步骤很容易做到。
请注意,上面的示例适用于SQL-Server,您可能需要为Access稍微更改一下。在任何情况下,您都可以在这里找到许多关于如何在Access下比较两行的示例。如前所述,您还可以使用Left Join而不是子查询来比较行。
答案 1 :(得分:0)
我提出了解决这个问题的查询,它不是那么简单
SELECT
ItmDtIni.PO
,ItmDtIni.POItem AS [PO Item]
,ROUND(ItmDtIni.QtyPending - ItmDtEnd.QtyPending, 3) AS [Qty Delivered]
,ROUND((ItmDtIni.QtyPending - ItmDtEnd.QtyPending) * ItmDtEnd.Price, 2) AS [Value delivered(US$)]
//Filtering subqueries to bring only the items in the date interval to make a self join
FROM (((SELECT
PO
,POItem
,QtyPending
,MIN(Date) AS MinDate
FROM Item
WHERE Date BETWEEN FORMAT(begin_date, 'dd/mm/yyyy') AND FORMAT(end_date, 'dd/mm/yyyy')
GROUP BY
PO
,POItem
,QtyPending) AS ItmDtIni
//Self join filtering to bring only items in the date interval with the previously filtered table
INNER JOIN (SELECT
PO
,POItem
,QtyPending
,Price
,MAX(Date) AS MaxDate
FROM Item
WHERE Date BETWEEN FORMAT(begin_date, 'dd/mm/yyyy') AND FORMAT(end_date, 'dd/mm/yyyy')
GROUP BY
PO
,POItem
,QtyPending
,Price) AS ItmDtEnd
ON ItmDtIni.PO = ItmDtEnd.PO
AND ItmDtIni.POItem = ItmDtEnd.POItem)
INNER JOIN PO
ON ItmDtEnd.PO = PO.Numero)
WHERE
//Showing only items that had a variation in the date interval
ROUND(ItmDtIni.QtyPending - ItmDtEnd.QtyPending, 3) <> 0
//Anchoring min date in the interval for each item found by the first subquery
AND ItmDtIni.MinDate = (SELECT MIN(Item.Date)
FROM Item
WHERE
ItmDtIni.PO = Item.PO
AND ItmDtIni.POItem = Item.POItem
AND Date BETWEEN FORMAT(begin_date, 'dd/mm/yyyy') AND FORMAT(end_date, 'dd/mm/yyyy'))
//Anchoring max date in the interval for each item found by the second subquery
AND ItmDtEnd.MaxDate = (SELECT MAX(Item.Date)
FROM Item
WHERE
ItmDtEnd.PO = Item.PO
AND ItmDtEnd.POItem = Item.POItem
AND Date BETWEEN FORMAT(begin_date, 'dd/mm/yyyy') AND FORMAT(end_date, 'dd/mm/yyyy'))