SQLite如何从分隔列文本中对另一个表中的值求和?
Posted
技术标签:
【中文标题】SQLite如何从分隔列文本中对另一个表中的值求和?【英文标题】:SQLite how to sum values from another table from a delimited column text? 【发布时间】:2020-10-22 21:00:23 【问题描述】:对不起,如果我的问题是重复的,如果是,我会删除,但我无法在其他任何地方找到我想做的事情。也许我不知道该怎么问。
我有 3 张桌子:
DROP TABLE IF EXISTS Order;
CREATE TABLE Order(
ORD_ID integer primary key
);
DROP TABLE IF EXISTS Product;
CREATE TABLE Product(
PRO_ID integer primary key
, PRO_Price double
, PRO_Kind integer
);
DROP TABLE IF EXISTS OrderItems;
CREATE TABLE OrderItems(
ORI_ID integer primary key
, ORD_ID integer
, PRO_ID integer
, ORI_AddedIngredients varchar
, FOREIGN KEY (PRO_ID) REFERENCES Product(PRO_ID)
, FOREIGN KEY (ORD_ID) REFERENCES Order(ORD_ID)
);
它们的内容是这样的:
Table Product
=========================================
PRO_ID | PRO_Price | PRO_Kind
1 5 1
2 11 1
3 2 2
4 2 2
5 2 2
=========================================
Table OrderItems WHERE ORD_ID = 1
=========================================
ORI_ID | ORD_ID | PRO_ID | ORI_AddedIngredients
1 1 1 '3, 4'
2 1 1 null
3 1 2 null
4 1 1 null
5 1 1 null
6 1 1 '3, 4, 5'
=========================================
我想做一个查询,从表中返回总和值,考虑到产品的添加成分,但是添加成分的产品与没有添加成分的产品不同
结果会是这样的:
QUERY RESULT
========================================
ORD_ID | PRO_ID | Total
1 1 9
1 1 5
1 1 11
1 2 11
但我不知道如何从像数组一样具有它们的字段中读取 ID,我可以在没有它的情况下进行查询,但是当我必须包含它们时,我不知道该怎么做。
如果你们有更好的方法来组织表格的内容,请告诉我。
【问题讨论】:
【参考方案1】:您必须将OrderItems
加入到Product
的2 个副本并聚合:
SELECT oi.ORI_ID, oi.ORD_ID, oi.PRO_ID,
MAX(p1.PRO_Price) + COALESCE(SUM(p2.PRO_Price), 0) Total
FROM OrderItems oi
INNER JOIN Product p1 ON p1.PRO_ID = oi.PRO_ID
LEFT JOIN Product p2 ON ',' || REPLACE(oi.ORI_AddedIngredients, ' ', '') || ',' LIKE '%,' || p2.PRO_ID || ',%'
GROUP BY oi.ORI_ID, oi.ORD_ID, oi.PRO_ID
如果ORI_AddedIngredients
列中没有空格,则使用REPLACE(oi.ORI_AddedIngredients, ' ', '')
代替ORI_AddedIngredients
。
请参阅demo。 结果:
> ORI_ID | ORD_ID | PRO_ID | Total
> -----: | -----: | -----: | ----:
> 1 | 1 | 1 | 9
> 2 | 1 | 1 | 5
> 3 | 1 | 2 | 11
【讨论】:
我不明白 LEFT JOIN 行的逻辑,它会转化为类似:LEFT JOIN Product p2 ON ',' || null || ',' LIKE '%,' || 1 || ',%'
这是比较什么和什么?
如果ORI_AddedIngredients
为null
,则此LEFT 连接将不匹配,因此COALESCE(SUM(p2.PRO_Price), 0)
将为0
。
以产品 3 和 4 作为订单 1 的成分为例,LEFT JOIN 行将是:LEFT JOIN Product p2 ON ',3,4,' LIKE '%,' || 1 || ',%'
?如果产品 3 存在,那将如何搜索产品比较表?对不起,我不明白这一行的逻辑
不是:...LIKE '%,' || 1 || ',%'
,而是LIKE '%,' || p2.PRO_ID || ',%'
,p2
是Product
的第二个副本,它的所有行都与',' || REPLACE(oi.ORI_AddedIngredients, ' ', '') || ','
进行比较
IN 对值列表进行操作,但 ORI_AddedIngredients
是一个包含逗号分隔值列表的字符串,这就是为什么您不能使用 IN 但可以使用对字符串进行操作的 LIKE .但是,是的,这是一般的想法。【参考方案2】:
根据@forpas 提供的查询,我能够构建产生我想要的问题结果的查询,谢谢@forpas:
SELECT
oi.ORD_ID
, oi.PRO_ID
, MAX(p1.PRO_ID) + COALESCE(SUM(p2.PRO_Price),0) Total
FROM OrderItems oi
JOIN Product p1 ON p1.PRO_ID = oi.PRO_ID
LEFT JOIN Product p2 ON ',' || REPLACE(oi.ORI_AddedIngredients, ' ', '') || ',' LIKE '%,' || p2.PRO_ID || ',%'
GROUP BY oi.PRO_ID, oi.ORD_ID, oi.ORI_AddedIngredients
本次查询的重点:
需要 REPLACE 以便 LIKE 比较正常工作,如果它有任何空白点,它只会总结其中一种成分而不是所有成分 折叠具有相同 ORI_AddedIngredients 值的成分就像在 GROUP BY 子句中添加字段一样简单,因此具有不同成分的相同产品 ID 会占用不同的行位置 在不使用 REPLACE 的情况下,我设法发现代码在数据库中记录了空格,而不仅仅是带有 ID 的分隔文本,但我将其保留在查询中,因为将来某个时候如果我忘记并结束添加空格仍然可以工作。再次感谢@forpas 提供查询和说明您是如何做到的。解释比发布答案更有价值,谢谢。
编辑:经过几天的查询工作以尝试获取每种可能的情况组合的最终结果,我放弃了尝试将成分与产品基值乘以该订单的产品数量相加的尝试,可能是因为我不知道如何正确执行,但我将值分成 2 列,并且每当我想要总数时,我只是将它们相加。 这是最终结果,是的,它适用于我的特定用例。
SELECT
ip.IPE_ID
, ip.PED_ID
, ip.PRO_ID
, p1.PRO_Nome
, ip.IPE_Adicionados
, ip.IPE_Removidos
, (SELECT COUNT(ip2.PRO_ID)
FROM ItensPedido ip2
WHERE ip2.PRO_ID = ip.PRO_ID
AND ip2.PED_ID = ip.PED_ID
AND (ip2.IPE_Adicionados = ip.IPE_Adicionados
OR ip2.IPE_Removidos = ip.IPE_Removidos
OR ip.IPE_Adicionados is null AND ip.IPE_Removidos is null
)
GROUP BY IPE_Adicionados
) as IPE_Qtd
, COALESCE(SUM(p2.PRO_Preco),0) as IPE_PIngredientes
, (SELECT COUNT(ip2.PRO_ID) * ip2.IPE_Valor
FROM ItensPedido ip2
WHERE ip2.PRO_ID = ip.PRO_ID
AND ip2.PED_ID = ip.PED_ID
AND (ip2.IPE_Adicionados = ip.IPE_Adicionados
OR ip2.IPE_Removidos = ip.IPE_Removidos
OR ip.IPE_Adicionados is null AND ip.IPE_Removidos is null
)
GROUP BY IPE_Adicionados
) as IPE_PParcial
FROM ItensPedido ip
JOIN Produto p1 ON p1.PRO_ID = ip.PRO_ID
LEFT JOIN Produto p2
ON "," || REPLACE(ip.IPE_Adicionados, " ", "") || "," LIKE "%," || p2.PRO_ID || ",%"
WHERE ip.PED_ID = :PED_ID
GROUP BY p1.PRO_Nome, ip.PED_ID, ip.IPE_Adicionados, ip.IPE_Removidos
这是我的测试数据库中的一个示例结果:
IPE_ID PED_ID PRO_ID PRO_Nome IPE_Adicionados IPE_Removidos IPE_Qtd IPE_PIngredientes IPE_PParcial
7 1 1 Hamburguer null null 2 0 10
1 1 1 Hamburguer 28, 29 null 2 8 10
9 1 1 Hamburguer 28, 29, 30 null 1 6 5
2 1 37 Refrigerante Lata null null 2 0 8
3 1 7 X-Bacon null 46, 47 1 0 11
【讨论】:
此查询未返回您的预期结果:dbfiddle.uk/… 到目前为止,我只检测到 1 个问题,即折叠的记录总数不是总和,因此它与 ID 为 1 的产品类似,即使在表中出现了 3 次,它只显示价格1,而不是所有 3 的总和。除此之外,它的工作原理...您用于测试我不知道的查询的该站点,从未使用过,并且该链接向我显示 404 错误。我使用 SQLite express 来操作我的查询,它提供的结果与我在我的应用程序中的结果相同。上面的查询就可以了。 上一个链接有效,这是另一个:db-fiddle.com/f/wuWX5drNfnExVWF4RBYgMS/0 @forpas 这个 .com 链接对我有用,但由于某种原因 .uk 不起作用,可能与我的 ISP 有关。感谢您提供帮助,我真的很感激。以上是关于SQLite如何从分隔列文本中对另一个表中的值求和?的主要内容,如果未能解决你的问题,请参考以下文章