2

2013 年 4 月 10 日編集

自分自身を明確にするために、私が達成しようとしていることの原則を示す別の (簡略化された) 例を追加しています。

T1 - PERSONHAS                T2 - PRODUCTNEED
ANTON    has    WHEEL         CAR      need    ENGINE
ANTON    has    ENGINE        CAR      need    WHEEL
ANTON    has    NEEDLE        SHIRT    need    NEEDLE
BERTA    has    NEEDLE        SHIRT    need    THREAD
BERTA    has    THREAD        JAM      need    FRUIT
BERTA    has    ENGINE        JAM      need    SUGAR

Q3 - PERSONCANMAKE
ANTON    canmake    CAR
BERTA    canmake    SHIRT

Q4 - PERSONCANNOTMAKE
ANTON    cannotmake    SHIRT
ANTON    cannotmake    FRUIT
BERTA    cannotmake    CAR
BERTA    cannotmake    FRUIT

T1 と T2 があり、Q3 と Q4 のクエリを作成したい

編集終了 2013 年 4 月 10 日

序文:

製品 (P) を作成するには、特定の一般的な機能 (C - 工場、供給、電気、水など) が必要です。製品マネージャーは、製品を作成するために必要なすべての一般的な機能を定義します。

あるロケーション (L) には特定の一般的な機能があります (C) ロケーション マネージャーは、そのロケーションが提供できる機能を定義します。これは、明確な YES、明確な NO のいずれかである場合もあれば、ロケーション マネージャーが特定の機能をまったくリストしていない場合もあります。

DB モデル:

次のルートエンティティを作成しました

Location (PK: L) - values L1, L2, L3     // in real ca. 250 rows of L
Product (PK: P) - values P1, P2          // in real ca. 150 rows of P
Capability (PK: C) - values C1, C2, C3   // in real ca.  80 rows of C

および次の子 (依存) エンティティ

ProductCapabilityAssignment:P, C (PK: P, C, FK: P, C)
    P1 C1
    P1 C2
    P2 C1
    P2 C3

LocationCapabilityAssignment: L, C, Status (Y/N) (PK: L, C, FK: L, C)
    L1 C1 Y
    L2 C1 Y
    L2 C2 Y
    L2 C3 N
    L3 C1 Y
    L3 C2 Y
    L3 C3 Y

仕事:

タスクは、特定の製品を特定の場所で生産できるかどうかを調べることです。これにより、製品に対して定義されたすべての機能がその場所に存在する必要があります。これに答えるために、私は自分自身を助けることができませんでした

Location と ProductCapabilityAssignment のデカルト積 (CL_Cart) を作成して、ロケーションごとに、可能なすべての製品とその cpability のニーズをリストするようにします。

CREATE VIEW CL_Cart AS
SELECT L.L, PCA.P, PCA.C
FROM Location AS L, ProductCapabilityAssignment AS PCA;

CL_Cart と LocationCapabilityAssignment の間に外部結合を作成して、場所が提供できるすべての機能を一致させます

CREATE VIEW Can_Produce AS
SELECT X.L, X.P, X.C, LCA.Status
FROM CL_CArt AS X LEFT JOIN LocationCapabilityAssignment AS LCA ON (X.C = LCA.C) AND (X.L = LCA.L);

最終的に私が得るように

SELECT L, P, C, Status
FROM Can_Produce;
    L1 P1 C1 Y
    L1 P1 C2 NULL        // C2 not listed for L1
    L1 P2 C1 Y
    L1 P2 C3 NULL        // C3 not listed for L1
    L2 P1 C1 Y
    L2 P1 C2 Y
    L2 P2 C1 Y
    L2 P2 C3 N           // C3 listed as "No" for L2
    L3 P1 C1 Y
    L3 P1 C2 Y
    L3 P2 C1 Y
    L3 P2 C3 Y

つまり、L1 は P1 も P2 も生成できず、L2 は P1 を生成でき、L3 は P1 と P2 の両方を生成できます。

そのため、特定の製品/場所を照会Can_Produceして、能力に関して持っているものと持っていないものを確認できます。また、全体的な YES/NO を調べることで、ショートカットを提供することもできますStatus="N" OR Status is NULL。その場合、製品は製造できません。

質問:

MSSQL、MySQL、Oracle などのリレーショナル データベース (まだ決定しておらず、私の影響力を超えています) の場合、この M:N 関係に対して正しいデータ モデルを選択したのか、それとももっとうまくやれるのか疑問に思っています。特に私はそれを恐れています。250 の場所、150 の製品、および平均で 1 つの製品は、+/- 10 の機能によって定義されます。つまり、375.000 行のデカルト積では、膨大なメモリ消費のためにパフォーマンスが低下します。

また、ストアド プロシージャは避けたいと思います。

どんな考えでも大歓迎です。

4

2 に答える 2

2
     --Environment Variables    
Declare @Parent table (id int identity(1,1) primary key, Name varchar(20))  
Declare @Components table (id int identity(1,1) primary key, Name varchar(20))  Insert into @Components (Name) values ('Engine'),('Wheel'),('Chassis'),('NEEDLE'),('THREAD'),('FRUIT'),('SUGAR')
Declare @Objects table (id int identity(1,1) primary key, Name varchar(20)) 
Declare @Template table (id int identity(1,1) primary key, Name varchar(20), ObjectID int, ComponentID int) 
Insert into @Template (Name, ObjectID, ComponentID) 
Select 'Vehicle', O.ID, C.ID from @Objects O, @Components C where O.Name = 'Car' and C.Name in ('Engine','Wheel','Chassis')union    
Select 'Clothing', O.ID, C.ID from @Objects O, @Components C where O.Name = 'Shirt' and C.Name in ('Needle','Thread') union 
Select 'Confectionary', O.ID, C.ID from @Objects O, @Components C where O.Name = 'JAM' and C.Name in ('FRUIT','SUGAR')  
Declare @AvailableMaterials table (id int identity(1,1) primary key, TestType varchar(20), ParentID int, ComponentID int)   

--Test Data 
Insert into @AvailableMaterials (TestType,ParentID,ComponentID) 
Select 'CompleteSet', P.ID, T.ComponentID from @Parent P, @Template T where P.Name = 'Driver' and T.Objectid = (Select ID from @Objects where Name = 'Car') union   
Select 'CompleteSet', P.ID,  T.ComponentID from @Parent P, @Template T where P.Name = 'Seamstress' and T.Objectid = (Select ID from @Objects where Name = 'Shirt') union    
Select 'IncompleteSet', P.ID,  T.ComponentID from @Parent P, @Template T where P.Name = 'Confectionarist' and T.Objectid = (Select ID from @Objects where Name = 'Jam')     
and T.ComponentID not in (Select ID from @Components where Name = 'FRUIT')  




--/*What sets are incomplete?*/ 
Select *    
from @AvailableMaterials    
where ID in (   
Select  SRCData.ID  
from @AvailableMaterials SRCData cross apply (Select ObjectID from @Template T where ComponentID = SRCData.ComponentID) ObjectsMatchingComponents   
inner join @Template T  
on SRCData.ComponentID = T.ComponentID  
and T.ObjectID = ObjectsMatchingComponents.ObjectID 
cross apply (Select ObjectID, ComponentID from @Template FullTemplate where FullTemplate.ObjectID = T.ObjectID and FullTemplate.ComponentID not in (Select ComponentID from @AvailableMaterials SRC where SRC.ComponentID = FullTemplate.ComponentID)) FullTemplate 
)   


/*What sets are complete?*/ 
Select *    
from @AvailableMaterials    
where ID not in (   
Select  SRCData.ID  
from @AvailableMaterials SRCData cross apply (Select ObjectID from @Template T where ComponentID = SRCData.ComponentID) ObjectsMatchingComponents   
inner join @Template T  
on SRCData.ComponentID = T.ComponentID  
and T.ObjectID = ObjectsMatchingComponents.ObjectID 
cross apply (Select ObjectID, ComponentID from @Template FullTemplate where FullTemplate.ObjectID = T.ObjectID and FullTemplate.ComponentID not in (Select ComponentID from @AvailableMaterials SRC where SRC.ComponentID = FullTemplate.ComponentID)) FullTemplate 
)   

やあ

これは私が思いつくことができる最高のものです...何が欠けているかを知るために、完全なセットが何であるかを知る必要があるという前提で機能します。何が欠けているかがわかれば、不完全なセットから完全なセットを見分けることができます。

インデックス付きの #tables に移動したとしても、このソリューションがうまくスケーリングされるとは思えません。たぶんだけど…

私も、よりクリーンなアプローチを見たいと思っています。上記のソリューションは、SQL 2012 バージョンで開発されました。デカルト効果をいくらか制限するクロス適用に注意してください。

お役に立てれば。

于 2013-11-26T13:29:33.490 に答える
1

使用しているデータベースはわかりませんが、SQL サーバーで機能する例を次に示します。他のデータベースで機能するために多くの変更は必要ありません...

WITH ProductLocation
AS
(
    SELECT  P.P,
            P.Name as ProductName,
            L.L,
            L.Name as LocationName
    FROM    Product P
    CROSS
    JOIN    Location L
),
ProductLocationCapability
AS
(
    SELECT  PL.P, 
            PL.ProductName, 
            PL.L, 
            PL.LocationName,
            SUM(PC.C) AS RequiredCapabilities,
            SUM(CASE WHEN LC.L IS NULL THEN 0 ELSE 1 END) AS FoundCapabilities
    FROM    ProductLocation PL
    JOIN    ProductCapabilityAssignment PC
            ON  PC.P = PL.P
    LEFT
    JOIN    LocationCapabilityAssignment LC
            ON  LC.L = PL.L
            AND LC.C = PC.C
    GROUP BY PL.P, PL.ProductName, PL.L, PL.LocationName
)
SELECT  PLC.P, 
        PLC.ProductName,
        PLC.L,
        PLC.LocationName,
        CASE WHEN PLC.RequiredCapabilities = PLC.FoundCapabilities THEN 'Y' ELSE 'N' END AS CanMake
FROM    ProductLocationCapability PLC

(フィールド名が正しいかどうかわかりません。スキーマの説明がよくわかりませんでした!)

于 2013-11-26T13:56:41.953 に答える