计算两个表之间不匹配的数字

时间:2018-02-22 15:23:29

标签: sql sql-server tsql

我的原始查询是按月计算从未订购的商品数量。

我在这里创建了一个sql小提琴http://sqlfiddle.com/#!18/e89a7/2

将下面的查询放在一起

SELECT COUNT(ItemNo)
FROM Item
WHERE ItemNo NOT IN 
(SELECT ItemNo
FROM Order1)

然而,这并不能做我想做的事情,我想知道我是否采取了错误的方式。我需要按订购的月份和年份进行分组,但NOT IN子句不允许我这样做。

示例数据:

CREATE TABLE Item (
    ItemNo varchar(10),
    MonthStocked varchar(10),
    YearStocked varchar(10)
);

CREATE TABLE Order1 (
    OrderNo int,
    ItemNo varchar(10),
    MonthOrdered varchar(10),
    YearOrdered varchar(10)
);

INSERT INTO Item (ItemNo, MonthStocked,YearStocked)
VALUES ('111','Feb', 2017),
('222','Jan',  2018),
('333','Feb', 2017),
('444','Feb', 2017),
('555','Jan', 2017),
('666','Jan', 2017);

INSERT INTO Order1 (OrderNo, ItemNo,MonthOrdered,YearOrdered)
VALUES ('897', '111', 'Dec', '2017'),
('657', '222', 'Nov', '2017'),
('896', '333', 'Nov' , '2017'),
('867', '333', 'Dec' , '2017'),
('234', '444', 'Nov' , '2017');

所需的输出:

| ItemsNotOrdered  |     Month    |     Year    |
|------------------|--------------|-------------|
|                3 |          Nov |        2017 |
|                4 |          Dec |        2017 |

3 个答案:

答案 0 :(得分:1)

您可以使用cross join生成所有项目/年/月组合。然后left joingroup by获得您想要的结果:

select ym.mon, ym.mon, count(*)
from item i cross join
     (select distinct MonthOrdered as mon, YearOrdered as yr from order1
     ) ym left join
     order1 o
     on i.itemno = o.itemno and ym.mon = o.MonthOrdered and ym.yr = o.YearOrdered 
where o.itemno is null
group by ym.yr, ym.mon;

Here是SQL小提琴。

答案 1 :(得分:0)

使用OUTER APPLY的另一个选项

SELECT   DISTINCT 
         MonthOrdered,
         YearOrdered,
         ItemsNotOrdered
FROM     Order1 o
OUTER APPLY (
         SELECT COUNT(ItemNo) ItemsNotOrdered
         FROM   Item i
         WHERE  NOT EXISTS (
            SELECT  ItemNo 
            FROM    Order1 o2
            WHERE   i.ItemNo = o2.ItemNo
            AND     o2.MonthOrdered = o.MonthOrdered
            AND     o2.YearOrdered = o.YearOrdered
         ) 
) ino

答案 2 :(得分:0)

我不喜欢你想要的输出,因为它错过了没有销售的月份。我也不喜欢那几个月不排序。

declare @item table (ItemNo varchar(10), MonthStocked varchar(10), YearStocked varchar(10))
INSERT INTO @Item (ItemNo, MonthStocked,YearStocked)
VALUES ('111','Feb', 2017),
       ('222','Jan', 2018),
       ('333','Feb', 2017),
       ('444','Feb', 2017),
       ('555','Jan', 2017),
       ('666','Jan', 2017);

declare @Order1 table (OrderNo int, ItemNo varchar(10), MonthOrdered varchar(10), YearOrdered varchar(10)) 
INSERT INTO @Order1 (OrderNo, ItemNo,MonthOrdered,YearOrdered)
VALUES ('897', '111', 'Dec', '2017'),
       ('657', '222', 'Nov', '2017'),
       ('896', '333', 'Nov', '2017'),
       ('867', '333', 'Dec', '2017'),
       ('234', '444', 'Nov', '2017');

declare @itemCount int = (select count(distinct ItemNo) from @item);

with CTEyymm as 
( select MonthStocked as mm, YearStocked as yy
    from @item 
  union
  select MonthOrdered, YearOrdered
    from @Order1
)

select yymm.yy, yymm.mm
     , (@itemCount - count(distinct(o.ItemNo))) as cnt  
  from CTEyymm yymm 
  left join @order1 o 
    on o.YearOrdered  = yymm.yy 
   and o.MonthOrdered = yymm.mm 
 group by yymm.yy, yymm.mm
 order by yymm.yy, yymm.mm;

如果您不关心空白月份,那么只需:

select o.YearOrdered, o.MonthOrdered
     , (@itemCount - count(distinct(o.ItemNo))) as cnt  
  from @order1 o 
 group by o.YearOrdered, o.MonthOrdered
 order by o.YearOrdered, o.MonthOrdered