如果在给定日期没有产品数量,则查询返回数量的SUM或0

时间:2012-05-03 09:41:35

标签: sql

我有以下4个表格:

----------
tblDates:

DateID

30/04/2012
01/05/2012
02/05/2012
03/05/2012

----------
tblGroups:

GroupID
Home
Table

----------
tblProducts:

ProductID   GroupID
Chair       Home
Fork        Table
Knife       Table
Sofa        Home

----------
tblInventory:

DateID      ProductID   Quantity

01/05/2012  Chair       2
01/05/2012  Sofa        1
01/05/2012  Fork        10
01/05/2012  Knife       10
02/05/2012  Sofa        1
02/05/2012  Chair       3
03/05/2012  Sofa        2
03/05/2012  Chair       3

我正在尝试编写一个查询,返回 tblDates 中的所有日期, tblGroups 中的所有 GroupIDs 以及每个日期中的项目总数量的的GroupID 即可。

我设法执行此操作,但只有get Sum(Quantity) GroupID DateID 非空。我想改为0。例如,对于上述数据,我想获得一行"02/05/2012 Table 0",因为01/05/12上“表格”组中的任何产品都没有数据。

到目前为止我的SQL查询是:

SELECT tblDates.DateID, 
       tblProducts.GroupID, 
       Sum(tblInventory.Quantity) AS SumOfQuantity
FROM (tblGroup 
     INNER JOIN tblProducts ON tblGroup.GroupID = tblProducts.GroupID) 
     INNER JOIN (tblDates INNER JOIN tblInventory ON tblDates.DateID = tblInventory.DateID) ON tblProducts.ProductID = tblInventory.ProductID
GROUP BY tblDates.DateID, tblProducts.GroupID;

我认为我应该在与 tblInventory 不同的表格上提供相同的查询,该列表会列出所有产品,而不是列出的产品为0而不是没有行,但我是由于我的数据库中的日期产品的数量不确定,查询可能太慢了。

可能有更好的方法来实现这一目标。

由于

3 个答案:

答案 0 :(得分:2)

要获得所有可能的GroupsDates组合,您必须CROSS JOIN这些表格。然后你可以LEFT JOIN到其他2个表:

SELECT
    g.GroupID
  , d.DateID
  , COALESCE(SUM(i.Quantity), 0)  AS Quantity
FROM 
        tblDates  AS d
    CROSS JOIN
        tblGroups AS g
    LEFT JOIN
            tblProducts  AS p
        JOIN
            tblInventory AS i
          ON i.ProductID = p.ProductID 
      ON  p.GroupID = g.GroupID
      AND i.DateID = d.DateID 
GROUP BY
    g.GroupID
  , d.DateID

答案 1 :(得分:0)

使用isnull()函数。将您的查询更改为:

    SELECT tblDates.DateID, tblProducts.GroupID,
            **ISNULL( Sum(tblInventory.Quantity),0)** AS SumOfQuantity
    FROM (tblGroup INNER JOIN tblProducts ON tblGroup.GroupID = tblProducts.GroupID) 
    INNER JOIN (tblDates INNER JOIN tblInventory ON tblDates.DateID = tblInventory.DateID)
            ON tblProducts.ProductID =  tblInventory.ProductID
    GROUP BY tblDates.DateID, tblProducts.GroupID;

答案 2 :(得分:0)

你没有说你正在使用哪个数据库,但我熟悉的是Oracle。

显然,如果你内部加入所有tbales,你将不会得到包含空值的行。如果对库存表使用外部联接,则也会出现问题,因为groupid列未在tblinventory中列出,并且只能外部联接到一个表。

我说你有两个选择。使用函数或在库存表中具有groupid列的副本。

所以,一个更好但更慢的解决方案:

create or replace
function totalquantity( d date, g varchar2 ) return number as
  result number;
begin
  select nvl(sum(quantity), 0 )
  into result
  from tblinventory i, tblproducts p
  where i.productid = p.productid
  and i.dateid = d
  and p.groupid = g;
  return result;
end;

select dateid, groupid, totalquantity( dateid, groupid )
from tbldates, tblgroups

或者,如果在库存表中包含groupid列。 (您仍然可以使用约束来保证完整性)

select d.dateid, i.groupid, nvl(i.quantity, 0) 
from tbldates d, tblinventory i 
where i.dateid(+) = d.dateid 
group by d.dateid, g.groupid 

希望这有帮助,   吉斯利