我正在规范某些表并遇到了一个我无法解决的问题。
旧的非规范化查询如下所示:
SELECT
SUM(allorderlines.COUNT),
products.NAME,
products.VOLUME,
people.NAME,
people.ID,
layout.POSTYPE,
IF( allorders.TOTAL = allorders.DISCOUNT, 1, 0 ) AS ISFREE
FROM
allorderlines
INNER JOIN allorders
ON allorderlines.ORDERID = allorders.ORDERID
INNER JOIN people
ON allorders.EMPLOYEE = people.ID
INNER JOIN layout
ON allorders.POSID = layout.ID
INNER JOIN products
ON allorderlines.PRODUCT = products.ID
WHERE
allorderlines.PRODUCT = ?
GROUP BY
people.ID,
layout.POSTYPE,
ISFREE
ORDER BY
layout.POSTYPE ASC,
people.NAME,
ISFREE ASC,
products.NAME
这意味着我可以将结果分组到订单是否免费(即免费)。
在我的规范化版本中,我没有allorders表(allorders.TOTAL
和allorders.DISCOUNT
)中可用订单的总和。为了确定订单是否免费,我需要SUM(allorderlines.LINEPRICE)
并查看它是否等于0.产品的行不会是0,但是具有订单贴现值的另一行将存在且等于如果订单总共是免费的产品总数:例如:
#Order 23123
Line 1: 2000
Line 2: 1000
Line 3 (discount): -3000
Free: true
#Order 23124
Line 1: 2000
Line 2: 1000
Line 3 (discount): -2000
Free: false
我无法弄清楚如何做到这一点并保留上述逻辑。我最接近的尝试是将ISFREE
替换为:{/ p>
IF(SUM(allorderlines.LINEPRICE) = 0,1,0) AS ISFREE
但是这给了我一个“不能通过ISFREE分组” - 错误,大概是因为我试图分组在这种情况下无法获得的东西。
一个显而易见的解决方案是在allorders.LINEPRICE
- 表中保存allorders
的总和,但这将是多余的,我正试图摆脱它。
请注意,DISCOUNT值以前是正数,而订单行现在为负值。因此(allorders.TOTAL = allorders.DISCOUNT)= FREE。
编辑:为了澄清,结果集应该类似于:
people.ID people.NAME SUM(COUNT) POSTYPE ISFREE
3 A name 4 1 1
3 A name 24 1 0
3 A name 2 2 1
3 A name 7 2 0
6 Another name 2 1 1
6 Another name 93 1 0
6 Another name 6 2 1
6 Another name 193 2 0
每个人可以有0到4行,0表示在给定产品的任何POSTYPE都不以任何价格出售,4表示至少1个免费,1个出售给两个POSTYPES(截至撰写时仅有2种类型。
答案 0 :(得分:1)
首先,让我们这样做。您正在寻找具有特定产品的任何订单。执行预查询以获取该产品的所有不同订单。然后加入按订单分组的订单行,以检测总免费网络订单。
最后,重新加入订单行和其他表格以获取您正在寻找的额外内容,但是按人,布局划分的组是免费标记,但按产品名称排序意味着显示所有产品订单的名称,但您的where子句仅查找ONE产品。
首先,首先是资格预审,还使用别名和长表名。
SELECT
QualByProd.OrderID,
SUM( AOL2.LinePrice ) as TotalOrder,
COUNT(*) as LineItemCount
FROM
( SELECT distinct AOL.OrderID
from AllOrderLines AOL
where AOL.Product = ? ) QualByProd
JOIN AllOrderLines AOL2
ON QualByProd.OrderID = AOL2.OrderID2
GROUP BY
QualByProd.OrderID
这将为您提供1)具有相关产品ID的每个订单,以及2)汇总整个订单中所有订单项的摘要,无论其是免费状态还是产品名称。但是在这一点上,它是每个合格订单的一条记录,总数(包括与合格产品相关的订单中的总订单项数)。现在,我们可以将整个查询作为原始内容的基础,例如......
SELECT
PR.NAME ProductName,
PR.VOLUME ProductVolume,
P.NAME PersonName,
P.ID PersonID,
L.POSTYPE,
IF( OkRecs.TotalOrder, 1, 0 ) AS ISFREE,
OkRecs.LineItemCount
FROM
( entire first query above by product ) as OkRecs
JOIN AllOrderLines AOL3
ON OkRecs.OrderID = AOL3.OrderID
JOIN AllOrders AO
ON OkRecs.OrderID = AO.OrderID
INNER JOIN people P
ON AO.EMPLOYEE = P.ID
INNER JOIN layout L
ON AO.POSID = L.ID
INNER JOIN products PR
ON AOL3.Product = PR.ID
WHERE
AOL3.PRODUCT = ?
ORDER BY
L.POSTYPE,
P.NAME,
IF( OkRecs.TotalOrder, 1, 0 )
PR.NAME
现在,您的分组表示汇总,但我认为您不希望这样。你可以让一个人有两个不同的订单...... 1个免费,5个付费的东西,总共6个订单。由于没有聚合,您可以按顺序排序。最后,免费物品。如果您想查看所有免费的订单,那么在所有POSType,个人和产品中,只需将IF()移动到第一个位置。