这是我正在处理的表的简化版本,即Orders
+-------------------+------------------+---------------+
| 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 |
+------+-----+-----------+
我尝试了很多查询,但从未接近这一点,甚至不确定是否可以完成。现在我正在计算客户端的组合,因此我执行了太多查询来获取频率。
答案 0 :(得分: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)
)
. . .
这更简洁,但可能会导致查询效率降低。
答案 1 :(得分: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。
答案 2 :(得分: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