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 |               |
+-------------------+------------------+---------------+

私がやりたいことは、ベース番号とロット番号に基づいて一意のエントリの数を取得することです。1 つはベース番号のセットで、もう 1 つはロット番号のセットです。たとえば、2 つのセットが Base In (1,2,3) で、Lot が (3,4,20) であるとします。

テーブルで組み合わせが見つかった回数を示すカウントを使用して、2 つのセットから (Base,Lot) のすべての可能な組み合わせを返すことができる SQL クエリを探しています。私の問題は、考えられるすべての組み合わせを含めたいということです。組み合わせが 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意図的に使用せずに が明示的に作成されることに注意してください。,

このクエリの最初の部分は、次のように記述することもできます (各ベースとロットに少なくとも 1 つのレコードがテーブルにあると仮定します)。

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 に答える