干草堆针相交 - 在干草堆中查找元素最多的集合

问题描述 投票:0回答:1

我需要找出某个功能的有效价格

  • 一个功能可以有 1 个或多个价格规则(规则数量 < 10; usually < 4)
  • 该功能的价格可能取决于订购的其他功能
  • 根据订购的其他功能(F2、F3 以下),价格可能会降低或增加。
  • 部分功能对F1的价格没有影响(F6、F8、F9以下)。

带有示例记录的 Sqlfiddle 演示

大海捞针(订单)中的每个特征(此处

F1
)必须与价格规则相匹配。有效价格是特征交集最多的价格。

此图显示了价格规则与不同订单之间的映射。与功能 F1 相关的价格基于价格规则表中的功能与订单中的功能之间的交集。

示例

  • F1
    的价格取决于功能
    (F1, F2, F3)
  • 特征
    F1
    的价格可以通过选择
    F1
    的价格规则来确定,该规则在与干草堆的交集中具有最多的元素(顺序)。

此示例具有针对功能

F1
的三个价格规则和三个不同的订单。

  • 订单 1 只有
    F1
    F1
    的价格规则相匹配;正确的价格是6
  • 订单 2 在 haystack 中有两个匹配特征 (
    F1+F2
    ) 与
    F1
    的 Pricerule 相匹配;正确的价格是4
  • 订单 3 有 3 个匹配 (
    F1+F2+F3
    ) 的
    F1
    ;正确的价格是2

此查询是我尝试连接记录,但存在许多重复和错误的连接记录

SELECT op.OrderId, op.Id as OrderPositionId, op.FeatureId, 
       f.Featurename, pr.Price 
FROM OrderPositions op 
INNER JOIN  FeatureCombinations fc ON op.FeatureId = fc.FeatureId
INNER JOIN Features f on op.FeatureId = f.Id
INNER JOIN PriceRules pr ON fc.PriceRuleId = pr.Id;

带有示例记录的 Sqlfiddle 演示

从目前的结果来看,所有带有(x)的记录都是错误的

订单ID 订单位置ID 功能 ID 功能名称 价格
401 211 1 F1 6
402 221× 1 F1 6
403 231× 1 F1 6
401 211 1 F1 4
402 221× 1 F1 4
403 231× 1 F1 4
402 222× 2 F2 4
403 232× 2 F2 4
401 211× 1 F1 2
402 221× 1 F1 2
403 231 1 F1 2
402 222× 2 F2 2
403 232× 2 F2 2
403 233× 3 F3 2

问题

如何确定某个功能的哪个价格规则最匹配 (

elements from order ∩ elements from pricerule
)?

用于创建包含记录的表的 SQL 语句

创建表

CREATE TABLE Features(
  Id    INTEGER PRIMARY KEY, 
  Featurename  TEXT
);
CREATE TABLE PriceRules(
  Id     INTEGER PRIMARY KEY, 
  Price  REAL   
);
CREATE TABLE FeaturesPriceRules(
  FeatureId   INTEGER, 
  PriceRuleId INTEGER,
  FOREIGN KEY(FeatureId) REFERENCES Features(Id),
  FOREIGN KEY(PriceRuleId) REFERENCES PriceRules(Id)
);

CREATE TABLE FeatureCombinations(
  PriceRuleId INTEGER,
  FeatureId   INTEGER,   
  FOREIGN KEY(PriceRuleId) REFERENCES PriceRules(Id),
  FOREIGN KEY(FeatureId) REFERENCES Features(Id)  
);

CREATE TABLE OrderPositions(
  Id INTEGER  PRIMARY KEY, 
  OrderId   INTEGER,   
  FeatureId   INTEGER,     
  FOREIGN KEY(FeatureId) REFERENCES Features(Id)  
);

创建记录


INSERT INTO Features (Id, Featurename)
VALUES (1, 'F1'), (2, 'F2'), (3, 'F3'),
       (4, 'F6'), (5, 'F7'), (6, 'F9'),
       (7, 'E1'), (8, 'ZA2');

INSERT INTO PriceRules (Id, Price)
VALUES (101, '6.00'), (102, '4.00'), (103, '2.00'),
       (105, '24.00'), (106, '22.00');  
    
INSERT INTO FeaturesPriceRules (FeatureId, PriceRuleId)
VALUES (1, 101), (1, 102), (1, 103),(7, 105),(7, 106);  
               
INSERT INTO FeatureCombinations (PriceRuleId, FeatureId)
VALUES (101, 1), (102, 1), (102, 2),
       (103, 1), (103, 2),(103, 3), 
       (105, 7), (106, 7), (106, 8); 
       
INSERT INTO OrderPositions(Id, OrderId, FeatureId)
VALUES (211, 401, 1), (221, 402, 1),(222, 402, 2),
(231, 403, 1),(232, 403, 2),(233, 403, 3);         
   

另请参阅此 带有示例记录的 Sqlfiddle 演示

sql sqlite intersection set-theory
1个回答
0
投票

注意:在此查询中,我实现了 CTE,用于计算订单是否符合规则。

答案:

;WITH cteFeatureCombinationsNeeded AS (
  SELECT fc.PriceRuleId, IFNULL(COUNT(fc.FeatureId), 0) countOfFeaturesNeeded
  FROM FeatureCombinations fc
  GROUP BY fc.PriceRuleId
  )   
, cteFeatureCombinationsProvided AS (
  SELECT op.OrderId, fc.PriceRuleId, fc.FeatureId,
    IFNULL(COUNT(fc.FeatureId), 0) countOfFeaturesProvided
  FROM OrderPositions op
  LEFT JOIN FeatureCombinations fc
    ON op.FeatureId = fc.FeatureId
  WHERE fc.PriceRuleId IS NOT NULL
  GROUP BY op.OrderId, fc.PriceRuleId
)

SELECT op.OrderId, op.Id as OrderPositionId, op.FeatureId, 
   f.Featurename, MIN(pr.Price)     
FROM OrderPositions op
LEFT JOIN FeatureCombinations fc
  ON op.FeatureId = fc.FeatureId
LEFT JOIN cteFeatureCombinationsNeeded cfcrn
  ON cfcrn.PriceRuleId = fc.PriceRuleId
LEFT JOIN cteFeatureCombinationsProvided cfcrp
  ON cfcrp.PriceRuleId = fc.PriceRuleId
  AND cfcrp.OrderId = op.OrderId
INNER JOIN Features f
   ON f.Id = cfcrp.FeatureId
INNER JOIN PriceRules pr
   ON pr.Id = cfcrp.PriceRuleId
WHERE 
  countOfFeaturesNeeded = countOfFeaturesProvided
GROUP BY op.Id, op.FeatureId
ORDER BY op.OrderId, cfcrp.countOfFeaturesProvided, fc.FeatureId, pr.Price

另请参阅此 带有示例记录的 Sqlfiddle 演示

从当前结果所有记录:

订单ID 订单位置ID 功能 ID 功能名称 价格
401 211 1 F1 6
402 221 1 F2 4
402 222 2 F2 4
403 231 1 F3 2
403 232 2 F3 2
403 233 3 F3 2

用于创建包含记录的表的 SQL 语句
创建表格

CREATE TABLE Features(
  Id    INTEGER PRIMARY KEY, 
  Featurename  TEXT
);
CREATE TABLE PriceRules(
  Id     INTEGER PRIMARY KEY, 
  Price  REAL   
);
CREATE TABLE FeaturesPriceRules(
  FeatureId   INTEGER, 
  PriceRuleId INTEGER,
  FOREIGN KEY(FeatureId) REFERENCES Features(Id),
  FOREIGN KEY(PriceRuleId) REFERENCES PriceRules(Id)
);

CREATE TABLE FeatureCombinations(
  PriceRuleId INTEGER,
  FeatureId   INTEGER,   
  FOREIGN KEY(PriceRuleId) REFERENCES PriceRules(Id),
  FOREIGN KEY(FeatureId) REFERENCES Features(Id)  
);

CREATE TABLE OrderPositions(
  Id INTEGER  PRIMARY KEY, 
  OrderId   INTEGER,   
  FeatureId   INTEGER,     
  FOREIGN KEY(FeatureId) REFERENCES Features(Id)  
);

创建记录

INSERT INTO Features (Id, Featurename)
VALUES (1, 'F1'), (2, 'F2'), (3, 'F3'),
       (4, 'F6'), (5, 'F7'), (6, 'F9'),
       (7, 'E1'), (8, 'ZA2');

INSERT INTO PriceRules (Id, Price)
VALUES (101, '6.00'), (102, '4.00'), (103, '2.00'),
       (105, '24.00'), (106, '22.00');  
    
INSERT INTO FeaturesPriceRules (FeatureId, PriceRuleId)
VALUES (1, 101), (1, 102), (1, 103),(7, 105),(7, 106);  
               
INSERT INTO FeatureCombinations (PriceRuleId, FeatureId)
VALUES (101, 1), (102, 1), (102, 2),
       (103, 1), (103, 2),(103, 3), 
       (105, 7), (106, 7), (106, 8); 
       
INSERT INTO OrderPositions(Id, OrderId, FeatureId)
VALUES (211, 401, 1), (221, 402, 1),(222, 402, 2),
(231, 403, 1),(232, 403, 2),(233, 403, 3);  
© www.soinside.com 2019 - 2024. All rights reserved.