Mysql 如何在表格中获得满足不同标准的产品和价格列表
我有一个定价表如下: 定价表 我需要找到合同ID列表和特定年龄组的ID(1岁、2岁或3岁)。对于儿童来说,年龄从-到也需要考虑 下面的查询1个成人、2个2&4岁的儿童和1个老年人似乎正在工作,但只返回与年龄组1匹配的IDMysql 如何在表格中获得满足不同标准的产品和价格列表,mysql,sql,Mysql,Sql,我有一个定价表如下: 定价表 我需要找到合同ID列表和特定年龄组的ID(1岁、2岁或3岁)。对于儿童来说,年龄从-到也需要考虑 下面的查询1个成人、2个2&4岁的儿童和1个老年人似乎正在工作,但只返回与年龄组1匹配的ID SELECT contractId,id FROM tbl_contract_price cp1 WHERE contractId IN (SELECT contractId FROM tbl_contract_price cp2 WHERE contractId IN
SELECT contractId,id
FROM tbl_contract_price cp1
WHERE contractId IN
(SELECT contractId FROM tbl_contract_price cp2
WHERE contractId IN
(SELECT contractId FROM tbl_contract_price cp3
WHERE cp1.ageGroup = 1 AND (cp2.ageGroup = 2 AND cp2.ageFrom <= 2 AND 2 <= cp2.ageTo OR cp2.ageGroup = 2 AND cp2.ageFrom <= 4 AND 4 <= cp2.ageTo ) AND cp3.ageGroup = 3))
有什么我遗漏的吗?基于一些假设,我创建了以下内容来帮助您开始。请注意,您需要加强您的数据完整性,即确保每个产品的所有可能年龄都包含在价格中,等等
CREATE TABLE Pricing (
ID int not null,
productId int not null,
ContractId int not null,
ageGroup int not null,
ageFrom int not null,
ageTo int not null,
sellingPrice int not null,
PRIMARY KEY (ID)
);
INSERT INTO Pricing (ID, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (1, 1, 1, 1, 0, 2, 0);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (2, 1, 1, 1, 3, 13, 20);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (3, 1, 1, 2, 18, 55, 80);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (4, 1, 1, 3, 56, 119, 60);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (5, 1, 2, 1, 3, 13, 0);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (6, 1, 2, 2, 18, 55, 85);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (7, 2, 2, 3, 55, 119, 90);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (8, 2, 2, 2, 18, 55, 90);
CREATE TABLE ValidDates (
ID int not null,
priceId int not null,
fromDate date not null,
toDate date not null,
PRIMARY KEY (ID)
);
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (1, 1, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (2, 2, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (3, 2, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (4, 3, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (5, 3, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (6, 4, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (7, 5, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (8, 5, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (9, 6, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (10, 6, '2018-07-01', '2018-07-31');
CREATE TABLE Products (
ID int not null,
PRIMARY KEY (ID)
);
CREATE TABLE Quotes (
ID int not null,
age int
);
INSERT INTO Quotes (Id, age) VALUES (1, 70);
INSERT INTO Quotes (Id, age) VALUES (1, 25);
INSERT INTO Quotes (Id, age) VALUES (1, 1);
INSERT INTO Quotes (Id, age) VALUES (1, 4);
我建议您使用一个临时报价表,以便在输入的数量上有更多的灵活性。您可以看到下面的数据示例。或者,更好的方法是在业务逻辑层中处理该逻辑
如果两个合同产生相同的价格,则需要应用任何平局断路器逻辑,等等
CREATE TABLE Pricing (
ID int not null,
productId int not null,
ContractId int not null,
ageGroup int not null,
ageFrom int not null,
ageTo int not null,
sellingPrice int not null,
PRIMARY KEY (ID)
);
INSERT INTO Pricing (ID, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (1, 1, 1, 1, 0, 2, 0);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (2, 1, 1, 1, 3, 13, 20);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (3, 1, 1, 2, 18, 55, 80);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (4, 1, 1, 3, 56, 119, 60);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (5, 1, 2, 1, 3, 13, 0);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (6, 1, 2, 2, 18, 55, 85);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (7, 2, 2, 3, 55, 119, 90);
INSERT INTO Pricing (id, productId, ContractId, ageGroup, ageFrom, ageTo, sellingPrice) Values (8, 2, 2, 2, 18, 55, 90);
CREATE TABLE ValidDates (
ID int not null,
priceId int not null,
fromDate date not null,
toDate date not null,
PRIMARY KEY (ID)
);
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (1, 1, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (2, 2, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (3, 2, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (4, 3, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (5, 3, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (6, 4, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (7, 5, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (8, 5, '2018-07-01', '2018-07-31');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (9, 6, '2018-06-01', '2018-06-30');
INSERT INTO ValidDates (id, priceId, fromDate, toDate) VALUES (10, 6, '2018-07-01', '2018-07-31');
CREATE TABLE Products (
ID int not null,
PRIMARY KEY (ID)
);
CREATE TABLE Quotes (
ID int not null,
age int
);
INSERT INTO Quotes (Id, age) VALUES (1, 70);
INSERT INTO Quotes (Id, age) VALUES (1, 25);
INSERT INTO Quotes (Id, age) VALUES (1, 1);
INSERT INTO Quotes (Id, age) VALUES (1, 4);
然后,您可以使用以下查询根据产品id、所选日期和报价id(包含特定报价的所有期限)计算您的总价
场景:游览日期=2018年6月22日;产品=1,报价=1,年龄=1,4,25,70
SELECT @tourdate := '2018-06-22', @productid := 1, @quoteid := 1;
显示如何检索相关信息的第一个查询
SELECT productid, contractId, ageGroup, ageFrom, ageTo,
SUM(CASE WHEN age BETWEEN ageFrom AND ageTo THEN 1 ELSE 0 END) AS PAXCount, sellingPrice
FROM ValidDates
LEFT JOIN Pricing
ON priceId = Pricing.ID
LEFT JOIN Products
ON productId = Products.ID
LEFT JOIN Quotes
ON Quotes.ID = @quoteid
WHERE (@tourdate BETWEEN fromDate AND toDate) AND productid = @productid
GROUP BY productid, contractid, ageGroup, ageFrom, ageTo, sellingPrice;
第二个查询是在第一个查询的基础上构建的,它聚合了总数,这样您就有了排名的总成本
SELECT contractId, SUM(sellingPrice * PAXCount) FROM (
SELECT productid, contractId, ageGroup,
SUM(CASE WHEN age BETWEEN ageFrom AND ageTo THEN 1 ELSE 0 END) AS PAXCount, sellingPrice
FROM ValidDates
LEFT JOIN Pricing
ON priceId = Pricing.ID
LEFT JOIN Products
ON productId = Products.ID
LEFT JOIN Quotes
ON Quotes.ID = @quoteid
WHERE (@tourdate BETWEEN fromDate AND toDate) AND productid = @productid
GROUP BY productid, contractid, ageGroup, sellingPrice) P
GROUP BY contractid
ORDER BY SUM(sellingPrice * PAXCount)
#LIMIT 1;
您可以取消对Limit 1的注释,以获得最便宜的包,但您需要了解该限制
您需要确保您的数据完整性得到加强,即,对于每个产品和日期范围,所有可能的年龄都需要
请注意,由于合同id 2未涵盖0岁的儿童和70岁的老年人,因此85美元的总额具有误导性。如果输入计数为4,您可以添加逻辑来检查合同是否可以满足所有年龄段的要求,检查合同是否确实包含四个人,等等
您可能需要根据需要清理引号表。这肯定不是最有效的方法,但它应该根据您的需求工作
例如,将查询更改为以下内容:
SELECT @PAXCount := COUNT(*) FROM Quotes WHERE id = @quoteid;
或者,您也可以很容易地从应用程序中传递它。
然后,检查以确保计数匹配
SELECT contractId, SUM(sellingPrice * PAXCount) AS TotalPrice, SUM(PAXCount) AS TotalPAXCOUNT
FROM (
SELECT productid, contractId, ageGroup,
SUM(CASE WHEN age BETWEEN ageFrom AND ageTo THEN 1 ELSE 0 END) AS PAXCount, sellingPrice
FROM ValidDates
LEFT JOIN Pricing
ON priceId = Pricing.ID
LEFT JOIN Products
ON productId = Products.ID
LEFT JOIN Quotes
ON Quotes.ID = @quoteid
WHERE (@tourdate BETWEEN fromDate AND toDate) AND productid = @productid
GROUP BY productid, contractid, ageGroup, sellingPrice) P
GROUP BY contractid
HAVING @PAXCount = SUM(PAXCount)
ORDER BY SUM(sellingPrice * PAXCount)
#LIMIT 1;
这样,只会显示覆盖所有乘客的合同id
您的输入选择标准和预期输出是什么?您提到了验证日期,但我怎么知道哪些日期在您的范围内,所以我假设日期是输入的一部分,以及产品id?您能提到所需的输出吗?@作者对此表示抱歉。刚刚用更多信息编辑了主要帖子。请看这是否足够好。谢谢你们。@GarimaGupta对那个家伙很抱歉。刚刚用更多信息编辑了主要帖子。请看这是否足够好。谢谢。如何将这三个表链接在一起?似乎没有一个通用的键,所以我可以判断哪个价格从哪个日期到哪个日期是有效的。定价表没有有效日期FK等。谢谢。客户已经提出了一些小的修改,并正在进行中。我相信这会对我有很大帮助。我还想知道,当有许多并发查询时,这样一个临时表是否会影响数据库性能?我同意你的担忧。这不是一个临时表,而是一个事务表,但这是绕过数据结构和您的需求所需要的一种技巧。这就是为什么您可能应该考虑更新数据模式,使用适当的缓存,并让业务层为您进行计算。在应用程序中提取相关的定价信息,根据需要缓存并计算价格。