1

这是我正在处理的表格的简化版本,即订单

+-------------------+------------------+---------------+
| Order_Base_Number | Order_Lot_Number | Other Cols... |
+-------------------+------------------+---------------+
|                 1 |                3 |               |
|                 1 |                3 |               |
|                 1 |                4 |               |
|                 1 |                4 |               |
|                 1 |                4 |               |
|                 1 |                5 |               |
|                 2 |                3 |               |
|                 2 |                5 |               |
|                 2 |                9 |               |
|                 2 |               10 |               |
+-------------------+------------------+---------------+

我想要做的是根据基数和批号计算唯一条目的数量。我有两组数字,一组是基数,另一组是一组批号。例如,假设这两组是 Base In (1,2,3),Lot 在 (3,4,20)。

我正在寻找一个 SQL 查询,它可以从两个集合中返回 (Base,Lot) 的所有可能组合,其计数显示在表中找到该组合的次数。我的问题是我想包括所有可能的组合,如果组合不在 Orders 表中,我希望计数显示为零。所以,我正在寻找的输出是这样的。

+------+-----+-----------+
| Base | Lot | Frequency |
+------+-----+-----------+
|    1 |   3 |    2      |
|    1 |   4 |    3      |
|    1 |  20 |    0      |
|    2 |   3 |    1      |
|    2 |   4 |    0      |
|    2 |  20 |    0      |
|    3 |   3 |    0      |
|    3 |   4 |    0      |
|    3 |  20 |    0      |
+------+-----+-----------+

我尝试了很多查询,但从未接近过这个,甚至不确定是否可以完成。现在我正在弄清楚客户端的组合,因此我执行了太多查询来获取频率。

4

3 回答 3

1

也许最清晰的方法是从 CTE 列表开始:

with bases as (
    select 1 as base from dual union all
    select 2 as base from dual union all
    select 3 as base from dual
   ),
     lots as (
    select 3 as lot from dual union all
    select 4 as lot from dual union all
    select 20 as lot from dual
   )
select b.base, l.lot, count(Order_Base_Number) as Frequency
from bases b cross join lots l left outer join
     Orders o
     on o.base = b.base and o.lot = l.lot
group by b.base, l.lot

请注意,这使得cross join明确的,故意不使用,笛卡尔积。

该查询的第一部分也可以写成如下所示(假设每个基数和批次在表中至少有一条记录):

with bases as (
     select distinct base
     from Orders  -- or some other table, perhaps Orders ?
     where base in (1, 2, 3)
    ),
     select distinct lot
     from Orders  -- or some other table, perhaps Lots ?
     where lot in (3, 4, 20)
    )
. . .

这更简洁,但可能导致查询效率降低。

于 2013-01-10T19:24:11.987 回答
0

您在最里面的子查询中需要的是调用CROSS JOIN,它获取记录的笛卡尔积(所有可能的组合)。这就是你没有JOIN..ON condition也没有的时候得到的WHERE

SELECT Base.Id as baseid, Lot.Id as lotid FROM Bases, Lots

现在将其放入子查询和LEFT JOIN其他内容中:

SELECT ... FROM 
   (SELECT Base.Id as baseid, Lot.Id as lotid 
           FROM Bases, Lots) baseslots
   LEFT JOIN Orders ON Order_Base_Number = baseid, 
             Order_Lot_Number = lotid ....

有了这个LEFT JOIN,你会得到 NULL 不存在的组合。使用COALESCE(或类似的东西)将它们变成 0。

于 2013-01-10T19:19:31.200 回答
0

我没有 Oracle 来测试它,但这是我要做的:

CREATE TABLE pairs AS
(
SELECT DISTINCT Base.Order_Base_Number, Lot.Order_Lot_Number 
FROM ORDERS Base
CROSS JOIN ORDERS Lot
);

CREATE TABLE counts AS
(
SELECT Order_Base_Number, Order_Lot_Number, Count(*) AS C
FROM ORDERS 
GROUP BY Order_Base_Number, Order_Lot_Number
);

SELECT P.Order_Base_Number, P.Order_Lot_Number, COALESCE(C.C,0) AS [Count]
FROM Pairs P
LEFT JOIN counts C ON P.Order_Base_Number = C.Order_Base_Number 
             AND P.Order_Lot_Number = C.Order_Lot_Number
于 2013-01-10T19:22:22.807 回答