如何使用查询找出客户最喜欢的品牌?

时间:2012-01-27 16:16:38

标签: sql ms-access

我想以这种形式生成一个表(或查询结果)

+---------------------+---------------------+
| Email               | Favourite Brand ID  |
+---------------------+---------------------+
| customer@gmail.com  |                  89 |
+-                   -+-                   -+
| another@gmail.com   |                 193 |
+-                   -+-                   -+

我设法编写了一个查询,该查询生成一个唯一品牌ID列表,其中包含客户电子邮件地址以及客户购买该品牌的次数。结果看起来像这样:

+---------------------+-----------+---------------+
| Email               | Brand ID  | CountOfOrders |
+---------------------+-----------+---------------+
| customer@gmail.com  |        89 |            10 |
+-                   -+-         -+-             -+
| another@gmail.com   |       193 |            32 |
+-                   -+-         -+-             -+
| duplicate@gmail.com |        20 |             2 |
+-                   -+-         -+-             -+
| duplicate@gmail.com |        47 |             5 |
+-                   -+-         -+-             -+

显然duplicate@gmail.com已经从BrandID 20购买了两次而BrandID 47购买了5次,这就是他们出现两次的原因。大多数客户都是从多个品牌购买的。

从这些信息中我如何构建查询以获取他们最常购买的品牌ID?我尝试了以下但是它只是超时:

SELECT [table1].Email, [table1].Brand, [table1].CountOfBrand
FROM [Customer Brand Purchases] AS [table1]
GROUP BY [table1].Email, [table1].Brand, [table1].CountOfBrand
WHERE [table1].CountOfBrand=(
    SELECT TOP 1 [table2].CountOfBrand 
    FROM [Customer Brand Purchases] AS [table2] 
    WHERE [table2].Email = [table1].Email 
    ORDER BY [table2].CountOfBrand DESC
);

哦,我不得不使用Microsoft Access。感谢。

4 个答案:

答案 0 :(得分:2)

因此,您的GROUP BY子句应列出聚合数据函数MAX()应折叠到的值。我刚刚在SQLite中这样做了(因为我无法打开Microsoft Access):

sqlite> create table purchases ( email varchar(255), brand_id int, order_count int );

sqlite> select * from purchases;

sqlite> insert into purchases values( 'customer@gmail.com', 89, 10 );
sqlite> insert into purchases values( 'another@gmail.com', 193, 32 );
sqlite> insert into purchases values( 'duplicate@gmail.com', 20, 2 );
sqlite> insert into purchases values( 'duplicate@gmail.com', 47, 5 );

sqlite> select * from purchases
customer@gmail.com|89|10
another@gmail.com|193|32
duplicate@gmail.com|20|2
duplicate@gmail.com|47|5

sqlite> .mode column
sqlite> .headers on
sqlite> select email, brand_id, max( order_count )from purchases group by email;

email              brand_id    order_count
-----------------  ----------  -----------
another@gmail.com  193         32               
customer@gmail.co  89          10               
duplicate@gmail.c  47          5       

我相信这就是你要找的,对吗?

答案 1 :(得分:2)

我不愿意回答这个问题,因为甚至协助开发一个带有表名[Customer Customer Purchases]的数据库让我觉得有点不舒服。

My Access SQL有点生疏,但我确信98%可以使用:

SELECT   CBP.Email, CBP.Brand AS [Favourite Brand ID]
FROM    [Customer Brand Purchases] AS CBP
        INNER JOIN
        (   SELECT  [Email], MAX(CountofBrand) AS [MaxCountofBrand]
            FROM    [Customer Brand Purchases]
            GROUP BY [Email]
        ) AS [MaxCBP]
            ON CBP.Email = MaxCBP.Email
            AND CBP.CountOfBrand = MaxCBP.MaxCountOfBrand

唯一的缺点是,如果特定客户订购了2个品牌相同的次数,那么它将返回2行。您需要使用MAX语句的其他子查询来解决此问题。

EDIT /附录:

如果绝对必要,查询会返回每个电子邮件地址1个结果,那么您需要考虑特定电子邮件地址已购买2个品牌和相同数量的情况,无法确定哪个或哪些是最喜欢的他们是最喜欢的。如果是我,我会在应用程序级别处理此问题,并将喜爱的品牌连接成一个字符串。但是,它可以在SQL中完成,只要知道可以使用此隐藏一个或多个品牌:

SELECT   CBP.Email, CBP.Brand AS [Favourite Brand ID]
FROM    [Customer Brand Purchases] AS CBP
        INNER JOIN
        (   SELECT  CBP.Email, MAX(CBP.Brand) AS MaxBrand
            FROM    [Customer Brand Purchases] AS CBP
                    INNER JOIN
                    (   SELECT  [Email], MAX(CountofBrand) AS MaxCountofBrand
                        FROM    [Customer Brand Purchases]
                        GROUP BY [Email]
                    ) AS MaxCBP
                        ON CBP.Email = MaxCBP.Email
                        AND CBP.CountOfBrand = MaxCBP.MaxCountOfBrand
            GROUP BY Email
        ) AS MaxCBP
            ON CBP.Email = MaxCBP.Email
            AND CBP.Brand = MaxCBP.Brand

答案 2 :(得分:2)

Gareth的回答对我来说是正确的。我使用基本查询中的数据测试了自己的尝试,该数据存储在名为Customer_Brand_Purchases的表中。我还重命名了Brand_ID列。

SELECT
    c1.Email,
    c1.Brand_ID AS [Favourite Brand ID]
FROM
    Customer_Brand_Purchases AS c1
    INNER JOIN (
        SELECT
            Email,
            Max(CountOfOrders) AS MaxOfCountOfOrders
        FROM Customer_Brand_Purchases
        GROUP BY Email
        ) AS c2
    ON
        (c1.Email = c2.Email)
        AND (c1.CountOfOrders = c2.MaxOfCountOfOrders)
ORDER BY c1.Email;

我可以确认这在Access 2007中有效,这意味着它产生我认为你想要的输出而没有错误消息。

Email               Favourite Brand ID
another@gmail.com                  193
customer@gmail.com                  89
duplicate@gmail.com                 47

然而,我的查询与Gareth的版本几乎相同。我可以提供为什么我可能会为你工作的唯一原因是他没有避免在子查询中使用方括号。

在某些情况下(我的详细信息不清楚),Access'查询设计器将从此表单重写子查询:

SELECT q.* FROM (SELECT something FROM YourTable) AS q

到此......

SELECT q.* FROM [SELECT something FROM YourTable]. AS q

在第二种形式中,如果子查询包含方括号,db引擎将会阻塞。顺便说一句,这是避免使用需要包围的对象名称的一个原因......例如包含空格的名称。

OTOH,如果我的版本也失败了,我怀疑你的基本查询源太复杂,数据库引擎无法在这里使用它。如果是这样,请遵循Philippe的建议,建立在原始源表而不是[Customer Brand Purchases]查询的基础上。

答案 3 :(得分:1)

根据您提出的评论之一,您似乎在这里查询查询。

如果您真的想了解客户最喜欢的品牌,我相信回到原始表格,在您的客户,订单行,产品参考和“品牌”表格上建立查询会更容易。