未能找到此特定问题的答案。需要在不同产品上按月分组的库存总数。源数据具有日期字段,一个用于IN,一个用于OUT。特定月份的总计数将包括在特定月份之前具有IN日期的所有行的总和,只要该出日期为空或特定月份之后的日期。
显然,我可以通过使用WHERE子句编写count(distinct productID)查询来获取任何给定月份的计数,该子句声明IN Date在我感兴趣的月份之前(IE 2012年9月)和Out Date为null或在9/2012之后:
Where ((in_date <= '2012-09-30') AND (out_date >= '2012-09-01' or out_date is null))
如果产品在9月份的某一天甚至是库存的一部分,我希望它能算出9月12日以后的日期。以下示例数据。而不是查询特定的月份,我该怎么做呢:
原始数据 - 每一行都是单独的项目
InDate OutDate ProductAttr ProductID 2008-04-05 NULL Blue 101 2008-06-04 NULL Red 125 2008-01-01 2012-06-01 Blue 134 2008-12-10 2012-10-09 Red 129 2009-10-15 2012-11-01 Blue 153 2012-10-01 2013-06-01 Red 149
进入这个?:
Date ProductAttr Count 2008-04 Blue 503 2008-04 Red 1002 2008-05 Blue 94 2008-05 Red 3004 2008-06 Blue 2000 2008-06 Red 322
通过分组,我可以将原始数据转换为按月分组的格式:
InDate OutDate Value Count 2008-05 2012-05 Blue 119 2008-05 2008-06 Red 333 2008-05 2012-10 Blue 4 2008-05 NULL Red 17488 2008-06 2012-11 Blue 711 2008-06 2013-02 Red 34
如果你想知道截至2012年10月有多少产品是'IN',你可以计算所有行的计数,除了2. Group on Value以保持蓝色和红色分开。因为OutDate在2012年10月之前排除了第2行。
提前感谢。
编辑:
Gordon Linoff的解决方案就像我需要它一样。我现在唯一的问题是查询的大小和效率,因为我遗漏的部分是产品属性实际上位于不同的表中,然后是IN / OUT日期,我还需要加入第三个表限制某种类型的产品(例如ForSale)。我尝试了两种不同的方法,它们都可以工作并返回相同的数据,但这两种方法都需要很长时间才能自动生成此报告:
select months.mon, count(distinct d.productID), d.ProductAttr
from (select '2008-10' as mon union all
select '2008-11' union all
select '2008-12' union all
select '2009-01'
) months left outer join
t
on months.mon >= date_format(t.Indate, '%Y-%m') and
(months.mon <= date_format(t.OutDate, '%Y-%m') or t.OutDate is NULL)
join x on x.product_id = t.product_id and x.type = 'ForSale'
join d on d.product_id = x.product_id and d.type = 'Attribute'
group by months.mon, d.ProductAttr;
在没有最后两个连接的情况下,通过添加产品属性的子查询和where / exclusion进行了上述尝试 - 这似乎运行相同或稍慢:
select months.mon, count(distinct t.productID), (select ProductAttr from d where productid = t.productID and type = 'attribute' limit 1)
from (select '2008-10' as mon union all
select '2008-11' union all
select '2008-12' union all
select '2009-01'
) months left outer join
t
on months.mon >= date_format(t.Indate, '%Y-%m') and
(months.mon <= date_format(t.OutDate, '%Y-%m') or t.OutDate is NULL)
WHERE exists (select 1 from x where x.productid = t.productID and x.type = 'ForSale')
group by months.mon, d.ProductAttr;
使用我需要依赖3个源表的额外数据来提高效率的任何想法(1仅用于排除)。提前谢谢。
答案 0 :(得分:0)
您可以通过生成所需月份的列表来完成此操作。最简单的方法是在MySQL中手动执行此操作(尽管在Excel中生成代码可以使这更容易)。
然后使用左连接和聚合来获取所需的信息:
select months.mon, t.ProductAttr, count(distinct t.productID)
from (select '2008-10' as mon union all
select '2008-11' union all
select '2008-12' union all
select '2009-01'
) months left outer join
t
on months.mon >= date_format(t.Indate, '%Y-%m') and
(months.mon <= date_format(t.OutDate, '%Y-%m) or t.OutDate is NULL)
group by t months.mon, t.ProductAttr;
此版本将所有比较作为字符串进行。您正在以“月”的粒度工作,格式YYYY-MM在比较方面做得很好。
编辑:
您确实需要在输出中每个月都需要。如果您每个月都有产品,那么您可以这样做:
select months.mon, t.ProductAttr, count(distinct t.productID)
from (select distinct date_format(t.InDate, '%Y-%m') as mon
from t
) months left outer join
t
on months.mon >= date_format(t.InDate, '%Y-%m') and
(months.mon <= date_format(t.OutDate, '%Y-%m) or t.OutDate is NULL)
group by t months.mon, t.ProductAttr;
这可以从数据中抽出几个月。