SQL 按月查询组 ID 重叠(通过内部联接)
SQL Query to group ID overlap (via inner join) by month
我试图找到一个查询,该查询将提供在同一个月内与 2 个不同实体进行过交易的客户数量。换句话说,customer_ids 在同一个月内与 company_a 和 company_b 进行了交易。这是我目前所拥有的:
SELECT Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date) AS
payment_month,
Count(UNIQUE(company_a_customers.customer_id))
FROM (SELECT *
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )) AS company_a_customers
INNER JOIN (SELECT *
FROM my_table
WHERE ( merchant_name = 'company_b' )) AS
company_b_customers
ON company_a_customers.customer_id =
company_b_customers.customer_id
GROUP BY Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date)
问题是,这让我得到 运行 每月与公司 A 进行交易的所有客户的总数 曾经 进行过交易与公司 B.
如果我将其缩减到特定月份,它显然会给我正确的重叠,因为查询仅获取该月份的 ID:
SELECT Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date) AS
payment_month,
Count(UNIQUE(company_a_customers.customer_id))
FROM (SELECT *
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )
AND transaction_date >= '2017-06-01'
AND transaction_date <= '2017-06-30') AS company_a_customers
INNER JOIN (SELECT *
FROM my_table
WHERE ( merchant_name = 'company_b' )
AND transaction_date >= '2017-06-01'
AND transaction_date <= '2017-06-30') AS
company_b_customers
ON company_a_customers.customer_id =
company_b_customers.customer_id
GROUP BY Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date)
我如何在一个查询中执行此操作以获取在给定月份内与两家公司进行过交易的客户的每月总计?
期望的结果:第二个查询的输出,但针对数据库中的每个月。也就是说:
2017 年 1 月:xx,xxx 重叠客户
2017 年 2 月:xx,xxx 重叠客户
2017 年 3 月:xx,xxx 重叠客户
非常感谢。
您只需计算每个客户 ID 每月 merchant_names 的数量,就可以在一次查询中获得所需的结果。使用 HAVING > 1 将仅向您显示与两者都有交易的客户(如果有更多匹配项,则显示更多,例如 '%company_a%')。
SELECT
EXTRACT(Year from transaction_date)||EXTRACT(Month from transaction_date) as payment_month
,customer_id
,COUNT(DISTINCT merchant_name) as CompanyCount
FROM my_table
WHERE transaction_date >= '2017-06-01' AND transaction_date <= '2017-06-30'
AND (merchant_name = 'company_b' or merchant_name LIKE '%company_a%')
GROUP BY
EXTRACT(Year from transaction_date)||EXTRACT(Month from transaction_date)
,customer_id
HAVING COUNT(DISTINCT merchant_name) > 1
您可以简单地为两者计算 year/month,然后将其添加为连接条件,但这不是很有效,因为它可能会产生巨大的中间结果。
您最好检查每个 month/customer 是否使用条件聚合与两个商家进行交易。然后按月数:
SELECT payment_month, count(*)
FROM
( SELECT Extract(year FROM transaction_date)
|| Extract(month FROM transaction_date) AS payment_month,
customer_id
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )
OR ( merchant_name = 'company_b' )
GROUP BY payment_month,
customer_id
-- both merchants within the same months
HAVING SUM(CASE WHEN merchant_name LIKE '%company_a%' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN merchant_name = 'company_b' THEN 1 ELSE 0 END) > 0
) AS dt
GROUP BY 1
你的 payment_month
计算太复杂了(而且返回的字符串格式不正确)。
获取 year/month 作为字符串:
TO_CHAR(transaction_date, 'YYYYMM')
作为数字:
EXTRACT(YEAR FROM transaction_date) * 100
+ EXTRACT(MONTH FROM transaction_date)
或计算第一个月:
TRUNC(transaction_date, 'mon')
我试图找到一个查询,该查询将提供在同一个月内与 2 个不同实体进行过交易的客户数量。换句话说,customer_ids 在同一个月内与 company_a 和 company_b 进行了交易。这是我目前所拥有的:
SELECT Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date) AS
payment_month,
Count(UNIQUE(company_a_customers.customer_id))
FROM (SELECT *
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )) AS company_a_customers
INNER JOIN (SELECT *
FROM my_table
WHERE ( merchant_name = 'company_b' )) AS
company_b_customers
ON company_a_customers.customer_id =
company_b_customers.customer_id
GROUP BY Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date)
问题是,这让我得到 运行 每月与公司 A 进行交易的所有客户的总数 曾经 进行过交易与公司 B.
如果我将其缩减到特定月份,它显然会给我正确的重叠,因为查询仅获取该月份的 ID:
SELECT Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date) AS
payment_month,
Count(UNIQUE(company_a_customers.customer_id))
FROM (SELECT *
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )
AND transaction_date >= '2017-06-01'
AND transaction_date <= '2017-06-30') AS company_a_customers
INNER JOIN (SELECT *
FROM my_table
WHERE ( merchant_name = 'company_b' )
AND transaction_date >= '2017-06-01'
AND transaction_date <= '2017-06-30') AS
company_b_customers
ON company_a_customers.customer_id =
company_b_customers.customer_id
GROUP BY Extract(year FROM company_a_customers.transaction_date)
|| Extract(month FROM company_a_customers.transaction_date)
我如何在一个查询中执行此操作以获取在给定月份内与两家公司进行过交易的客户的每月总计?
期望的结果:第二个查询的输出,但针对数据库中的每个月。也就是说:
2017 年 1 月:xx,xxx 重叠客户 2017 年 2 月:xx,xxx 重叠客户 2017 年 3 月:xx,xxx 重叠客户
非常感谢。
您只需计算每个客户 ID 每月 merchant_names 的数量,就可以在一次查询中获得所需的结果。使用 HAVING > 1 将仅向您显示与两者都有交易的客户(如果有更多匹配项,则显示更多,例如 '%company_a%')。
SELECT
EXTRACT(Year from transaction_date)||EXTRACT(Month from transaction_date) as payment_month
,customer_id
,COUNT(DISTINCT merchant_name) as CompanyCount
FROM my_table
WHERE transaction_date >= '2017-06-01' AND transaction_date <= '2017-06-30'
AND (merchant_name = 'company_b' or merchant_name LIKE '%company_a%')
GROUP BY
EXTRACT(Year from transaction_date)||EXTRACT(Month from transaction_date)
,customer_id
HAVING COUNT(DISTINCT merchant_name) > 1
您可以简单地为两者计算 year/month,然后将其添加为连接条件,但这不是很有效,因为它可能会产生巨大的中间结果。
您最好检查每个 month/customer 是否使用条件聚合与两个商家进行交易。然后按月数:
SELECT payment_month, count(*)
FROM
( SELECT Extract(year FROM transaction_date)
|| Extract(month FROM transaction_date) AS payment_month,
customer_id
FROM my_table
WHERE ( merchant_name LIKE '%company_a%' )
OR ( merchant_name = 'company_b' )
GROUP BY payment_month,
customer_id
-- both merchants within the same months
HAVING SUM(CASE WHEN merchant_name LIKE '%company_a%' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN merchant_name = 'company_b' THEN 1 ELSE 0 END) > 0
) AS dt
GROUP BY 1
你的 payment_month
计算太复杂了(而且返回的字符串格式不正确)。
获取 year/month 作为字符串:
TO_CHAR(transaction_date, 'YYYYMM')
作为数字:
EXTRACT(YEAR FROM transaction_date) * 100
+ EXTRACT(MONTH FROM transaction_date)
或计算第一个月:
TRUNC(transaction_date, 'mon')