MySQL:将table连接到自身,消除重复行
MySQL: Joining a table to itself, eliminating duplicate rows
我有一个将 table 连接到自身的查询。结果包含重复行(某种程度上)。此查询的 objective 用于生成最常一起购买的产品列表。考虑这个查询:
SELECT o1.ITEM
,o2.ITEM as ITEM2
,o3.ITEM AS ITEM3
,count(DISTINCT o1.ORDERNUM) as oCount
FROM orders o1
INNER JOIN orders o2 ON o2.ORDERNUM = o1.ORDERNUM AND o2.ITEM != o1.ITEM
LEFT OUTER JOIN orders o3 ON o3.ORDERNUM = o1.ORDERNUM AND o3.ITEM != o2.ITEM AND o3.ITEM != o1.ITEM
GROUP BY o1.ITEM, o2.ITEM, o3.ITEM
ORDER BY oCount DESC
前 12 个结果:
+-------------+-------------+-------------+--------+
| ITEM | ITEM2 | ITEM3 | oCount |
+-------------+-------------+-------------+--------+
| 02B13.04.GP | 77A04.10 | 45A04.04.GP | 54 |
| 02B13.04.GP | 45A04.04.GP | 77A04.10 | 54 |
| 77A04.10 | 45A04.04.GP | 02B13.04.GP | 54 |
| 45A04.04.GP | 02B13.04.GP | 77A04.10 | 54 |
| 77A04.10 | 02B13.04.GP | 45A04.04.GP | 54 |
| 45A04.04.GP | 77A04.10 | 02B13.04.GP | 54 |
| 57B01.01.GP | 57B01.11.GP | 57B01.10.GP | 12 |
| 57B01.10.GP | 57B01.11.GP | 57B01.01.GP | 12 |
| 57B01.01.GP | 57B01.10.GP | 57B01.11.GP | 12 |
| 57B01.10.GP | 57B01.01.GP | 57B01.11.GP | 12 |
| 57B01.11.GP | 57B01.10.GP | 57B01.01.GP | 12 |
| 57B01.11.GP | 57B01.01.GP | 57B01.10.GP | 12 |
请注意,前 6 个结果是相同的连接,但顺序不同。第二个 6 个结果有相同的问题(并且这在整个结果中持续存在)。我的目标是为每个项目组创建一个记录,而不是为每个项目组的每个组合创建一个单独的行。
如何避免这些重复的结果?
我们也欢迎任何关于更有效的查询方法的建议(我想添加一个额外的连接,但是有 1,000,000 个订单,资源需求已经失控)。
============================================= ===
编辑:回答 Darshan 的问题
能否分享一下table结构:
table 包含所有订单的行。如果一个订单包含多个产品,则每个产品都有一行(给定订单的多行)。此查询中唯一需要关注的列是:
ORDERNUM CHAR : Order Number
ITEM CHAR : SKU for the item
QTY INT : Quantity purchased
ORDDATE DATETIME : Order Date
返回的结果:我需要的是我在上面的结果示例中列出的内容。 objective是获取一起购买次数最多的商品列表。
你要做的是消除重复的行,不管位置如何;一个技巧,因为您总是拥有项目的所有组合,所以根据 item1 < item2 < item3
的谓词过滤结果
这是一个可能的解决方案:
SELECT a.item, b.item, c.item, count(*)
from `orders` a left join orders b
on a.ordernum = b.ordernum and a.item <> b.item
left join orders c on a.ordernum = c.ordernum
and a.item <> c.item and b.item <> c.item
where a.item < b.item and b.item < c.item
group by a.item, b.item, c.item
order by count(*) desc
我有一个将 table 连接到自身的查询。结果包含重复行(某种程度上)。此查询的 objective 用于生成最常一起购买的产品列表。考虑这个查询:
SELECT o1.ITEM
,o2.ITEM as ITEM2
,o3.ITEM AS ITEM3
,count(DISTINCT o1.ORDERNUM) as oCount
FROM orders o1
INNER JOIN orders o2 ON o2.ORDERNUM = o1.ORDERNUM AND o2.ITEM != o1.ITEM
LEFT OUTER JOIN orders o3 ON o3.ORDERNUM = o1.ORDERNUM AND o3.ITEM != o2.ITEM AND o3.ITEM != o1.ITEM
GROUP BY o1.ITEM, o2.ITEM, o3.ITEM
ORDER BY oCount DESC
前 12 个结果:
+-------------+-------------+-------------+--------+
| ITEM | ITEM2 | ITEM3 | oCount |
+-------------+-------------+-------------+--------+
| 02B13.04.GP | 77A04.10 | 45A04.04.GP | 54 |
| 02B13.04.GP | 45A04.04.GP | 77A04.10 | 54 |
| 77A04.10 | 45A04.04.GP | 02B13.04.GP | 54 |
| 45A04.04.GP | 02B13.04.GP | 77A04.10 | 54 |
| 77A04.10 | 02B13.04.GP | 45A04.04.GP | 54 |
| 45A04.04.GP | 77A04.10 | 02B13.04.GP | 54 |
| 57B01.01.GP | 57B01.11.GP | 57B01.10.GP | 12 |
| 57B01.10.GP | 57B01.11.GP | 57B01.01.GP | 12 |
| 57B01.01.GP | 57B01.10.GP | 57B01.11.GP | 12 |
| 57B01.10.GP | 57B01.01.GP | 57B01.11.GP | 12 |
| 57B01.11.GP | 57B01.10.GP | 57B01.01.GP | 12 |
| 57B01.11.GP | 57B01.01.GP | 57B01.10.GP | 12 |
请注意,前 6 个结果是相同的连接,但顺序不同。第二个 6 个结果有相同的问题(并且这在整个结果中持续存在)。我的目标是为每个项目组创建一个记录,而不是为每个项目组的每个组合创建一个单独的行。
如何避免这些重复的结果?
我们也欢迎任何关于更有效的查询方法的建议(我想添加一个额外的连接,但是有 1,000,000 个订单,资源需求已经失控)。
============================================= ===
编辑:回答 Darshan 的问题
能否分享一下table结构:
table 包含所有订单的行。如果一个订单包含多个产品,则每个产品都有一行(给定订单的多行)。此查询中唯一需要关注的列是:
ORDERNUM CHAR : Order Number
ITEM CHAR : SKU for the item
QTY INT : Quantity purchased
ORDDATE DATETIME : Order Date
返回的结果:我需要的是我在上面的结果示例中列出的内容。 objective是获取一起购买次数最多的商品列表。
你要做的是消除重复的行,不管位置如何;一个技巧,因为您总是拥有项目的所有组合,所以根据 item1 < item2 < item3
的谓词过滤结果这是一个可能的解决方案:
SELECT a.item, b.item, c.item, count(*)
from `orders` a left join orders b
on a.ordernum = b.ordernum and a.item <> b.item
left join orders c on a.ordernum = c.ordernum
and a.item <> c.item and b.item <> c.item
where a.item < b.item and b.item < c.item
group by a.item, b.item, c.item
order by count(*) desc