SQL - 选择查询以获取具有来自不同产品系列的两个或更多产品的采购订单

时间:2016-03-30 18:32:26

标签: sql sql-server sql-server-2008 tsql having

我想知道如何重做/改进此查询(运行时间太长)。

一些背景信息: 订单ID => 'ID' 购买ID => '的pid' “表”是购买行的表,id是订单的id,订单可以有多行。例如,可以有三行ID为1,具有各种购买ID,因此:

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

Althoug我非常喜欢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)
        )
    )
)