SQL - Select 查询以获取具有来自不同产品线的两个或多个产品的采购订单
SQL - Select query to get purchase orders that have two or more products from different product lines
我想知道如何处理 rework/improve 这个查询(运行 花费的时间太长)。
一些背景信息:
订单编号 => 'id'
购买 ID => 'pid'
"Table"是一个table的采购行,id是一个订单的id,订单可以有多个行。例如,可以有 id 为 1 的三行,具有不同的购买 id,所以:
编号 | pid
1 | 3
1 | 3
1 | 46
查询的目的是查找从多个产品线购买的订单,例如 1、21、31、41 和 2、22、32、42。
下面的查询是我想出的,但是 运行 从所有子查询来看都非常慢,是否可以优化此查询或使用不同的、更快的查询获得相同的结果?
SELECT a.id
FROM Table AS a
GROUP BY a.id
HAVING (
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('1', '21', '31', '41') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('2', '22', '32', '42') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('3', '23', '33', '43') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('4', '24', '34', '44') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('5', '25', '35', '45') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('6', '26', '36', '46') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('7', '27', '37', '47') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('8', '28', '38', '48') AND id = a.id ) THEN 1 ELSE 0 END AS INT)
) > 1
编辑:
最终工作查询(比以前快 97%):
SELECT y.Id
FROM (SELECT x.Id,
x.productLine
FROM ( SELECT a.id,
CASE
WHEN a.pid IN ('1', '21', '31', '41') THEN 1
WHEN a.pid IN ('2', '22', '32', '42') THEN 2
WHEN a.pid IN ('3', '23', '33', '43') THEN 3
WHEN a.pid IN ('4', '24', '34', '44') THEN 4
WHEN a.pid IN ('5', '25', '35', '45') THEN 5
WHEN a.pid IN ('6', '26', '36', '46') THEN 6
WHEN a.pid IN ('7', '27', '37', '47') THEN 7
WHEN a.pid IN ('8', '28', '38', '48') THEN 8
ELSE 9
END AS productLine
FROM Table AS a
WHERE a.pid IN ('1', '21', '31', '41','2', '22', '32', '42','3', '23', '33', '43','4', '24', '34', '44','5', '25', '35', '45','6', '26', '36', '46','7', '27', '37', '47','8', '28', '38', '48')
) AS x
GROUP BY x.Id, x.productLine
) AS y
GROUP BY y.Id
HAVING COUNT(*) > 1
据我了解你的问题这个查询应该符合你的要求:
SELECT x.Id
FROM ( SELECT a.Id ,
CAST(a.pid AS INT) % 10 AS pid
FROM [Table] AS a
GROUP BY a.Id ,
CAST(a.pid AS INT) % 10
) x
GROUP BY x.Id
HAVING COUNT(*) > 1
考虑到新的假设后,查询应如下所示:
SELECT y.Id
(SELECT x.Id,
x.pid
FROM ( SELECT a.id,
CASE WHEN a.pid IN ('1', '21', '31', '41') THEN 1
WHEN a.pid IN ('2', '22', '32', '42') THEN 2
WHEN a.pid IN ('3', '23', '33', '43') THEN 3
WHEN a.pid IN ('4', '24', '34', '44') THEN 4
WHEN a.pid IN ('5', '25', '35', '45') THEN 5
WHEN a.pid IN ('6', '26', '36', '46') THEN 6
WHEN a.pid IN ('7', '27', '37', '47') THEN 7
WHEN a.pid IN ('8', '28', '38', '48') THEN 8
ELSE 9 END AS productLine
FROM Table AS a
) x
GROUP BY x.Id, x.pid) y
GROUP BY y.Id
HAVING COUNT(*) > 1
尽管我非常喜欢 Rafał 的解决方案,因为它为组提供了数字,但我想到了另一个更简单的解决方案,但无法更早地对其进行测试。
SELECT distinct(id) FROM store a
WHERE 4 = (
SELECT COUNT(DISTINCT(pid))
FROM store
where (id = a.id AND (
pid in (1, 21, 31, 41) OR
pid in (2, 22, 32, 42)
)
)
)
我想知道如何处理 rework/improve 这个查询(运行 花费的时间太长)。
一些背景信息: 订单编号 => 'id' 购买 ID => 'pid' "Table"是一个table的采购行,id是一个订单的id,订单可以有多个行。例如,可以有 id 为 1 的三行,具有不同的购买 id,所以:
编号 | pid
1 | 3
1 | 3
1 | 46
查询的目的是查找从多个产品线购买的订单,例如 1、21、31、41 和 2、22、32、42。
下面的查询是我想出的,但是 运行 从所有子查询来看都非常慢,是否可以优化此查询或使用不同的、更快的查询获得相同的结果?
SELECT a.id
FROM Table AS a
GROUP BY a.id
HAVING (
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('1', '21', '31', '41') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('2', '22', '32', '42') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('3', '23', '33', '43') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('4', '24', '34', '44') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('5', '25', '35', '45') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('6', '26', '36', '46') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('7', '27', '37', '47') AND id = a.id ) THEN 1 ELSE 0 END AS INT) +
CAST( CASE WHEN EXISTS (SELECT NULL FROM Table WHERE pid IN ('8', '28', '38', '48') AND id = a.id ) THEN 1 ELSE 0 END AS INT)
) > 1
编辑:
最终工作查询(比以前快 97%):
SELECT y.Id
FROM (SELECT x.Id,
x.productLine
FROM ( SELECT a.id,
CASE
WHEN a.pid IN ('1', '21', '31', '41') THEN 1
WHEN a.pid IN ('2', '22', '32', '42') THEN 2
WHEN a.pid IN ('3', '23', '33', '43') THEN 3
WHEN a.pid IN ('4', '24', '34', '44') THEN 4
WHEN a.pid IN ('5', '25', '35', '45') THEN 5
WHEN a.pid IN ('6', '26', '36', '46') THEN 6
WHEN a.pid IN ('7', '27', '37', '47') THEN 7
WHEN a.pid IN ('8', '28', '38', '48') THEN 8
ELSE 9
END AS productLine
FROM Table AS a
WHERE a.pid IN ('1', '21', '31', '41','2', '22', '32', '42','3', '23', '33', '43','4', '24', '34', '44','5', '25', '35', '45','6', '26', '36', '46','7', '27', '37', '47','8', '28', '38', '48')
) AS x
GROUP BY x.Id, x.productLine
) AS y
GROUP BY y.Id
HAVING COUNT(*) > 1
据我了解你的问题这个查询应该符合你的要求:
SELECT x.Id
FROM ( SELECT a.Id ,
CAST(a.pid AS INT) % 10 AS pid
FROM [Table] AS a
GROUP BY a.Id ,
CAST(a.pid AS INT) % 10
) x
GROUP BY x.Id
HAVING COUNT(*) > 1
考虑到新的假设后,查询应如下所示:
SELECT y.Id
(SELECT x.Id,
x.pid
FROM ( SELECT a.id,
CASE WHEN a.pid IN ('1', '21', '31', '41') THEN 1
WHEN a.pid IN ('2', '22', '32', '42') THEN 2
WHEN a.pid IN ('3', '23', '33', '43') THEN 3
WHEN a.pid IN ('4', '24', '34', '44') THEN 4
WHEN a.pid IN ('5', '25', '35', '45') THEN 5
WHEN a.pid IN ('6', '26', '36', '46') THEN 6
WHEN a.pid IN ('7', '27', '37', '47') THEN 7
WHEN a.pid IN ('8', '28', '38', '48') THEN 8
ELSE 9 END AS productLine
FROM Table AS a
) x
GROUP BY x.Id, x.pid) y
GROUP BY y.Id
HAVING COUNT(*) > 1
尽管我非常喜欢 Rafał 的解决方案,因为它为组提供了数字,但我想到了另一个更简单的解决方案,但无法更早地对其进行测试。
SELECT distinct(id) FROM store a
WHERE 4 = (
SELECT COUNT(DISTINCT(pid))
FROM store
where (id = a.id AND (
pid in (1, 21, 31, 41) OR
pid in (2, 22, 32, 42)
)
)
)