根据 JOIN 结果计算列中的值。

huangapple go评论63阅读模式
英文:

Calculate the value in a column based on JOIN results?

问题

I have a table, Account, which I am querying to identify old accounts based on sales records. An account may have multiple rows in a Property table. A property may be closed. If all properties on an account are closed, the account should be returned as it is old.

How do I identify an account where all properties are closed?

Additionally, an account is considered old if they have not purchased a Service in 24 months.

As an example, given the following tables:

+-------+-----------------------------------+
| ac_id | ac_email                          |
+-------+-----------------------------------+
|  1416 | bob@bob.com                       |
|  1419 | joe@joe.com                       |
+-------+-----------------------------------+

-- PROPERTY --

+------+---------------+-------+
| p_id | p_closed      | ac_id |
+------+---------------+-------+
|    3 |  FALSE        |  1416 |
|    6 |  TRUE         |  1419 |
|    7 |  TRUE         |  1419 |
+------+---------------+-------+

--SERVICE--

+------+------------+
| p_id | s_saledate |
+------+------------+
|    3 | 2010-03-17 |
|    3 | 2011-02-16 |
|    6 | 2022-11-14 |
|    7 | 2022-01-24 |
+------+------------+

I would expect the following returned table

| account_id | email                 | all_properties_closed | property_ids | latest_sale_date |
+------------+-----------------------+-----------------------+--------------+------------+--------------+------------------+
|       1416 | bob@bob.com           |       FALSE           |     9            | 2011-02-16       |
|       1419 | joe@joe.com           |       TRUE            |    6,7           | 2022-11-14       |
+------------+-----------------------+----------------+---------------------------+--------------+------------------+

Bob's account is returned because he's not had a Service in over 2 years & Joe's account is returned because he has had a service in 2 years, but all of his properties are closed.

This is my current query

 ac_id as account_id,
 GROUP_CONCAT(DISTINCT p_id) as property_ids,
 MAX(sale_date) as latest_sale_date
 FROM Account
 JOIN Property USING (ac_id)
 JOIN Service USING (p_id)
 GROUP BY ac.ac_id
 HAVING latest_sale_date < 2021-03-31

I imagine I need to use the ALL operator and WHERE to get the all_properties_closed column, but I'm unsure how. Do I need a subquery?

英文:

I have a table, Account, which I am querying to identify old accounts based on sales records. An account may have multiple rows in a Property table. A property may be closed. If all properties on an account are closed, the account should be returned as it is old.

How do I identify an account where all properties are closed?

Additionally, an account is considered old if they have not purchased a Service in 24 months.

As an example, given the following tables:

-- ACCOUNT --
+-------+-----------------------------------+
| ac_id | ac_email                          |
+-------+-----------------------------------+
|  1416 | bob@bob.com                       |
|  1419 | joe@joe.com                       |
+-------+-----------------------------------+

-- PROPERTY --

+------+---------------+-------+
| p_id | p_closed      | ac_id |
+------+---------------+-------+
|    3 |  FALSE        |  1416 |
|    6 |  TRUE         |  1419 |
|    7 |  TRUE         |  1419 |
+------+---------------+-------+

--SERVICE--

+------+------------+
| p_id | s_saledate |
+------+------------+
|    3 | 2010-03-17 |
|    3 | 2011-02-16 |
|    6 | 2022-11-14 |
|    7 | 2022-01-24 |
+------+------------+

I would expect the following returned table

+------------+-----------------------+-----------------------+--------------+------------+--------------+------------------+
| account_id | email                 | all_properties_closed | property_ids | latest_sale_date |
+------------+-----------------------+-----------------------+--------------+------------+--------------+------------------+
|       1416 | bob@bob.com           |       FALSE           |     9            | 2011-02-16       |
|       1419 | joe@joe.com           |       TRUE            |    6,7           | 2022-11-14       |
+------------+-----------------------+----------------+---------------------------+--------------+------------------+

Bob's account is returned because he's not had a Service in over 2 years & Joe's account is returned because he has had a service in 2 years, but all of his properties are closed.

This is my current query

 SELECT
 ac_id as account_id,
 GROUP_CONCAT(DISTINCT p_id) as property_ids,
 MAX(sale_date) as latest_sale_date
 FROM Account
 JOIN Property USING (ac_id)
 JOIN Service USING (p_id)
 GROUP BY ac.ac_id
 HAVING latest_sale_date &lt; 2021-03-31

I imagine I need to use the ALL operator and WHERE to get the all_properties_closed column, but I'm unsure how. Do I need a subquery?

答案1

得分: 1

你可以使用条件聚合来计算 all_properties_closed。假设 p_closed 是类似字符串的数据类型,那么代码如下:

SELECT
    ac_id as account_id,
    MIN(p_closed = 'FALSE') all_properties_closed,
    GROUP_CONCAT(DISTINCT p_id) as property_ids,
    MAX(sale_date) as latest_sale_date
FROM Account
JOIN Property USING (ac_id)
JOIN Service USING (p_id)
GROUP BY ac.ac_id
HAVING latest_sale_date < '2021-03-31' OR all_properties_closed

表达式 MIN(p_closed = 'FALSE') 当组内的任何 p_closed 具有非 'FALSE' 值时返回 0,否则返回 1。我们可以使用这个信息来在 HAVING 子句中进行筛选。

在正常用法中,你可以在列 p_closed 中使用 0/1 标志,然后可以这样做:

MIN(p_closed) all_properties_closed
英文:

You can compute all_properties_closed with conditional aggregation. Assuming that p_closed is of a string-like datatype, that would look like:

SELECT
    ac_id as account_id,
    MIN(p_closed = &#39;FALSE&#39;) all_properties_closed
    GROUP_CONCAT(DISTINCT p_id) as property_ids,
    MAX(sale_date) as latest_sale_date
FROM Account
JOIN Property USING (ac_id)
JOIN Service USING (p_id)
GROUP BY ac.ac_id
HAVING latest_sale_date &lt; 2021-03-31 OR all_properties_closed

Expression MIN(p_closed = &#39;FALSE&#39;) yields 0 if any p_closed in the group has a non-&#39;FALSE&#39; value, else it returns 1; we can use this information to filter in the HAVING clause.

In normal usage you would have a 0/1 flag in column p_closed, and we could just do:

MIN(p_closed) all_properties_closed

答案2

得分: 1

是的,您可以使用子查询来检查账户的所有属性是否已关闭。以下是修改后的查询,添加了all_properties_closed列:

SELECT
 ac.ac_id as account_id,
 ac.ac_email as email,
 GROUP_CONCAT(DISTINCT p.p_id) as property_ids,
 MAX(s.s_saledate) as latest_sale_date,
 NOT EXISTS (
   SELECT 1 FROM Property p2 WHERE p2.ac_id = ac.ac_id AND p2.p_closed = FALSE
 ) as all_properties_closed
FROM Account ac
LEFT JOIN Property p ON p.ac_id = ac.ac_id
LEFT JOIN Service s ON s.p_id = p.p_id
GROUP BY ac.ac_id
HAVING latest_sale_date < '2021-03-31' OR all_properties_closed

在子查询中,我们检查是否存在同一账户的未关闭属性(p2.p_closed = FALSE)。如果没有这样的属性,那么NOT EXISTS返回TRUE,表示所有属性已关闭。

请注意,我还将ac.ac_email添加到选择列表中,并使用LEFT JOIN而不是JOIN,以确保获取所有账户,即使它们没有任何属性或服务。

最后的HAVING子句包括识别旧账户的两个标准:那些在给定日期后没有服务的账户,或者那些所有属性都已关闭的账户。

英文:

Yes, you can use a subquery to check if all properties for an account are closed. Here's a modified version of your query that adds the all_properties_closed column:

SELECT
 ac.ac_id as account_id,
 ac.ac_email as email,
 GROUP_CONCAT(DISTINCT p.p_id) as property_ids,
 MAX(s.s_saledate) as latest_sale_date,
 NOT EXISTS (
   SELECT 1 FROM Property p2 WHERE p2.ac_id = ac.ac_id AND p2.p_closed = FALSE
 ) as all_properties_closed
FROM Account ac
LEFT JOIN Property p ON p.ac_id = ac.ac_id
LEFT JOIN Service s ON s.p_id = p.p_id
GROUP BY ac.ac_id
HAVING latest_sale_date &lt; 2021-03-31 OR all_properties_closed

In the subquery, we're checking if there exists a property for the same account that is not closed (p2.p_closed = FALSE). If there is no such property, then NOT EXISTS returns TRUE, indicating that all properties are closed.

Note that I've also added ac.ac_email to the select list and used LEFT JOIN instead of JOIN to ensure that we get all accounts, even if they don't have any properties or services.

The HAVING clause at the end includes both criteria for identifying old accounts: those with no services after the given date, or those with all properties closed.

huangapple
  • 本文由 发表于 2023年4月1日 00:19:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75900717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定