2

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

考虑以下数据:

-- 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_offers的ID。HH例如,对于优惠 foo34,我应该得到 HH #1,因为 HH #1 没有显示该类别的任何支出(HH #1 的类别 34 没有条目)。

因此,查找空数据时的第一直觉是外连接。所以我尝试了左连接cat_nbr。但这只会让我有消费的客户;我不知道如何告诉我在该类别中没有消费的客户的 ID。

如果重要的话,这是在 Netezza 上。

非常感谢您的任何帮助。

4

4 回答 4

4
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 ║
╚════╝

更新

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

输出

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

由于您提到您有一个非常大的表,因此添加复合INDEX将导致更快的查询执行。

ALTER TABLE t_catspend ADD INDEX (HH, CAT_NBR)

如果可能,t_catspend.CAT_NBR必须参考t_offers.CAT_NBR.

希望这可以帮助。

于 2013-06-02T03:38:58.907 回答
2

你在找这个吗?

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 |

这是SQLFiddle

于 2013-06-02T03:54:32.467 回答
0

我认为你在正确的轨道上,可能缺少 WHERE 标准?

SELECT *
FROM t_catspend spend
LEFT JOIN t_offers offers
 ON spend.CAT_NBR = offers.CAT_NBR
WHERE offers.CAT_NBR IS NULL
于 2013-06-02T03:54:15.990 回答
0

不知道这是否有效但有效。

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)
于 2013-06-03T02:24:30.230 回答