SQL:在一个类别中查找没有花费的客户

SQL:在一个类别中查找没有花费的客户,sql,business-intelligence,netezza,Sql,Business Intelligence,Netezza,我想我在这方面做得太久了,因为我很难回答一个非常简单的问题:在零售环境中,哪些客户没有在我提供优惠券的类别上花钱 考虑以下数据: -- The offer ID and the category for which it is valid. select * from t_offers OFFER CAT_NBR foo34 34 xxx30 30 baz60 60 bar50 50 -- The customer ID (HH) and their total spend

我想我在这方面做得太久了,因为我很难回答一个非常简单的问题:在零售环境中,哪些客户没有在我提供优惠券的类别上花钱

考虑以下数据:

-- The offer ID and the category for which it is valid.
select * from t_offers
OFFER   CAT_NBR
foo34   34
xxx30   30
baz60   60
bar50   50

-- The customer ID (HH) and their total spending by all
-- categories (not just the ones for which coupons are being offered).
-- PLEASE NOTE that when a customer has zero spend, there will NOT be an
--             entry in this table for that category.
select * from t_catspend
HH  CAT_NBR SPEND
1   30      5
1   60      7
2   34      8
我想得到的是:对于
t\u offers
中的每个优惠,每个没有该优惠类别支出的客户的
HH
ID。例如,对于offer foo34,我应该得到HH#1,因为HH#1没有显示该类别的任何支出(对于HH#1,34类没有条目)

因此,寻找空数据的第一反应是外部连接。因此,我在
cat\u nbr
上尝试了左连接。但这只会让我得到那些有消费的顾客;我不知道如何告诉我没有这类消费的客户的ID

这是在Netezza上,如果有关系的话

事先非常感谢您的帮助

SELECT  a.HH
FROM    t_catspend a
WHERE   NOT EXISTS
        (
            SELECT  null
            FROM    t_offers b
                    INNER JOIN t_catspend c
                        ON c.CAT_NBR = b.CAT_NBR
            WHERE   b.offer = 'foo34' AND
                    a.HH = c.HH
        )
GROUP   BY a.HH
输出

╔════╗
║ HH ║
╠════╣
║  1 ║
╚════╝
╔════╦═══════╦═════════╗
║ HH ║ OFFER ║ CAT_NBR ║
╠════╬═══════╬═════════╣
║  1 ║ bar50 ║      50 ║
║  1 ║ foo34 ║      34 ║
║  2 ║ baz60 ║      60 ║
║  2 ║ bar50 ║      50 ║
║  2 ║ xxx30 ║      30 ║
╚════╩═══════╩═════════╝
更新

SELECT  b.*, a.*
FROM    t_offers a
        CROSS JOIN (SELECT HH FROM t_catspend GROUP BY HH) b
        LEFT JOIN t_catspend x
          ON    a.CAT_NBR = x.CAT_NBR AND
                b.HH = x.HH
WHERE   x.CAT_NBR IS NULL
        -- AND a.offer = 'foo34'  -- <<== specific OFFER
ORDER   BY b.HH
因为您已经提到您有一个非常大的表,添加复合
索引将导致更快的查询执行

ALTER TABLE t_catspend ADD INDEX (HH, CAT_NBR)
如果可能的话,
t\u catspend.CAT\u NBR
必须参考
t\u offers.CAT\u NBR


希望这能有所帮助。

我认为你的思路是对的,可能没有达到标准

SELECT *
FROM t_catspend spend
LEFT JOIN t_offers offers
 ON spend.CAT_NBR = offers.CAT_NBR
WHERE offers.CAT_NBR IS NULL

你在找这个吗

SELECT b.cat_nbr, b.hh 
  FROM
(
 SELECT cat_nbr, hh
   FROM t_offers CROSS JOIN 
 ( 
   SELECT DISTINCT hh FROM t_catspend
 ) a
) b LEFT JOIN t_catspend s
    ON b.cat_nbr = s.cat_nbr AND b.hh = s.hh
 WHERE s.spend IS NULL
 GROUP BY b.cat_nbr, b.hh
基于提供的样本数据的输出:

| CAT_NBR | HH |
----------------
|      30 |  2 |
|      34 |  1 |
|      50 |  1 |
|      50 |  2 |
|      60 |  2 |

这里是

我不知道这是否有效,但有效

SELECT DISTINCT HH, offer FROM t_offers, t_catspend
WHERE (HH, offer) NOT IN
(SELECT HH, offer FROM t_offers t1, t_catspend t2
WHERE t1.cat_nbr = t2.cat_nbr)

您将如何筛选记录
foo34
?@SkyDrive OP对t_offers中每个优惠的确切文字,以及每个未在该优惠类别中消费的客户的HH ID。通过在
…)后面添加一个cat_nbr=34…
谢谢,peterm,可以很容易地对其进行过滤。当我决定跳到stackoverflow时,我正沿着笛卡尔连接路径走。。。这是不幸的,因为大约有3000万客户和100多个类别。不是世界末日,而是大世界!我会让你知道这是怎么回事。@Chris IMHO,在你的情况下,你必须以这样或那样的方式使用
交叉连接。JW的最新答案支持这一点。这看起来不错!有没有一种方法可以让所有的产品都通用,而不是为foo34定制?理想情况下,我会得到每个符合条件的东西的报价代码和hh ID(“符合条件”即类别中没有花费)。我已经更新了答案,以获得所有用户的状态。您需要在此上使用
CROSS-JOIN
将所有报价与所有
hh
值配对。不管怎样,尽管问吧<代码>:)