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
值配对。不管怎样,尽管问吧<代码>:)