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)
        )
    )
)