Return 如果在 UNION ALL 查询中未找到任何行,则为默认值
Return a default value if no rows are found in UNION ALL query
场景
我有一个从这个 question 开发的查询,优化的一部分是创建一个 MySql 视图,用于生成用户和销售的统计信息,问题是当有SELECT
行之一没有结果,结果 table.
中省略了它
问题
如果没有找到 SELECT
中的任何行,如何告诉 MySql 设置默认值(例如 0)?
代码
这是创建视图的代码
CREATE OR REPLACE VIEW user_events AS
SELECT 'Complete profiles' AS type, created_at
FROM users
WHERE completed_registration = 1
UNION ALL SELECT 'Incomplete profiles', created_at
FROM users
WHERE completed_registration = 0 AND verified_email = 1
UNION ALL SELECT 'Unverified profiles', created_at
FROM users
WHERE verified_email = 0
UNION ALL SELECT 'Onsite Teachers', created_at
FROM onsite_teachers
UNION ALL SELECT 'Onsite Teachers hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'onsite_teacher'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Translators', created_at
FROM translators
UNION ALL SELECT 'Translators hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'translator'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Interpreters', created_at
FROM interpreters
UNION ALL SELECT 'Interpreters hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'interpreter'
WHERE purchases.transaction_status = 'completed';
这是查询包括当前月份在内的最近6个月总计的代码。
SELECT
type,
COUNT(CASE
WHEN created_at >= CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY AS DATETIME)
THEN 1
END) AS 0_month_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 1 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 1_month_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 2 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 2_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 3 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 3 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 3_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 4 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 4 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 4_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 5 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 5 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 5_months_ago
FROM
user_events
GROUP BY
type;
当前输出
如果仔细观察没有 Interpreters hired
和 Translators hired
行,我希望设置这些行并在它们 return null
+=========================+===============+===============+===============+==============+===============+===============+
| type | 0_month_ago | 1_month_ago | 2_month_ago | 3_month_ago | 4_month_ago | 5_month_ago |
+=========================+===============+===============+===============+==============+===============+===============+
| Complete profiles | 7 | 20 | 14 | 25 | 30 | 7 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Incomplete profiles | 12 | 27 | 56 | 45 | 48 | 23 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Unverified profiles | 3 | 16 | 23 | 5 | 0 | 9 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Onsite Teachers | 11 | 36 | 8 | 15 | 46 | 12 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Onsite Teachers hired | 0 | 0 | 12 | 9 | 3 | 0 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Interpreters | 4 | 21 | 27 | 46 | 45 | 28 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Translators | 7 | 20 | 19 | 27 | 19 | 42 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
user_events
视图是一种日志,看起来像
type | created_at
======================+==============
Interpreters hired | 2014-12-12
Interpreters hired | 2014-12-14
Interpreters hired | 2014-12-16
Interpreters hired | 2015-01-02
但是,如果从未雇用过任何口译员,则不会有带有 type = 'Interpreters hired'
的行。在那种情况下,计数查询不可能凭空捏造一个 Interpreters hired
行。
一个解决方案是确保 Interpreters hired
行出现在 user_events
视图中,无论如何。您可以创建没有 created_at
日期的虚构行。这样,GROUP BY
总会有一些东西,但 COUNT()
.
不一定会有任何东西
CREATE OR REPLACE VIEW user_events AS
SELECT 'Complete profiles' AS type, created_at
FROM users
WHERE completed_registration = 1
UNION ALL SELECT 'Incomplete profiles', created_at
FROM users
WHERE completed_registration = 0 AND verified_email = 1
UNION ALL SELECT 'Unverified profiles', created_at
FROM users
WHERE verified_email = 0
UNION ALL SELECT 'Onsite Teachers', created_at
FROM onsite_teachers
UNION ALL SELECT 'Onsite Teachers hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'onsite_teacher'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Onsite Teachers hired', NULL
UNION ALL SELECT 'Translators', created_at
FROM translators
UNION ALL SELECT 'Translators hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'translator'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Translators hired', NULL
UNION ALL SELECT 'Interpreters', created_at
FROM interpreters
UNION ALL SELECT 'Interpreters hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'interpreter'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Interpreters hired', NULL;
场景
我有一个从这个 question 开发的查询,优化的一部分是创建一个 MySql 视图,用于生成用户和销售的统计信息,问题是当有SELECT
行之一没有结果,结果 table.
问题
如果没有找到 SELECT
中的任何行,如何告诉 MySql 设置默认值(例如 0)?
代码
这是创建视图的代码
CREATE OR REPLACE VIEW user_events AS
SELECT 'Complete profiles' AS type, created_at
FROM users
WHERE completed_registration = 1
UNION ALL SELECT 'Incomplete profiles', created_at
FROM users
WHERE completed_registration = 0 AND verified_email = 1
UNION ALL SELECT 'Unverified profiles', created_at
FROM users
WHERE verified_email = 0
UNION ALL SELECT 'Onsite Teachers', created_at
FROM onsite_teachers
UNION ALL SELECT 'Onsite Teachers hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'onsite_teacher'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Translators', created_at
FROM translators
UNION ALL SELECT 'Translators hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'translator'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Interpreters', created_at
FROM interpreters
UNION ALL SELECT 'Interpreters hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'interpreter'
WHERE purchases.transaction_status = 'completed';
这是查询包括当前月份在内的最近6个月总计的代码。
SELECT
type,
COUNT(CASE
WHEN created_at >= CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY AS DATETIME)
THEN 1
END) AS 0_month_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 1 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 1_month_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 2 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 2_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 3 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 3 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 3_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 4 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 4 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 4_months_ago,
COUNT(CASE
WHEN created_at BETWEEN CAST(CURDATE() - INTERVAL (DAYOFMONTH(CURDATE()) - 1) DAY - INTERVAL 5 MONTH AS DATETIME)
AND CAST(LAST_DAY(CURDATE() - INTERVAL 5 MONTH) + INTERVAL 1 DAY AS DATETIME)
THEN 1
END) AS 5_months_ago
FROM
user_events
GROUP BY
type;
当前输出
如果仔细观察没有 Interpreters hired
和 Translators hired
行,我希望设置这些行并在它们 return null
+=========================+===============+===============+===============+==============+===============+===============+
| type | 0_month_ago | 1_month_ago | 2_month_ago | 3_month_ago | 4_month_ago | 5_month_ago |
+=========================+===============+===============+===============+==============+===============+===============+
| Complete profiles | 7 | 20 | 14 | 25 | 30 | 7 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Incomplete profiles | 12 | 27 | 56 | 45 | 48 | 23 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Unverified profiles | 3 | 16 | 23 | 5 | 0 | 9 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Onsite Teachers | 11 | 36 | 8 | 15 | 46 | 12 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Onsite Teachers hired | 0 | 0 | 12 | 9 | 3 | 0 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Interpreters | 4 | 21 | 27 | 46 | 45 | 28 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
| Translators | 7 | 20 | 19 | 27 | 19 | 42 |
+-------------------------+---------------+---------------+---------------+--------------+---------------+---------------+
user_events
视图是一种日志,看起来像
type | created_at
======================+==============
Interpreters hired | 2014-12-12
Interpreters hired | 2014-12-14
Interpreters hired | 2014-12-16
Interpreters hired | 2015-01-02
但是,如果从未雇用过任何口译员,则不会有带有 type = 'Interpreters hired'
的行。在那种情况下,计数查询不可能凭空捏造一个 Interpreters hired
行。
一个解决方案是确保 Interpreters hired
行出现在 user_events
视图中,无论如何。您可以创建没有 created_at
日期的虚构行。这样,GROUP BY
总会有一些东西,但 COUNT()
.
CREATE OR REPLACE VIEW user_events AS
SELECT 'Complete profiles' AS type, created_at
FROM users
WHERE completed_registration = 1
UNION ALL SELECT 'Incomplete profiles', created_at
FROM users
WHERE completed_registration = 0 AND verified_email = 1
UNION ALL SELECT 'Unverified profiles', created_at
FROM users
WHERE verified_email = 0
UNION ALL SELECT 'Onsite Teachers', created_at
FROM onsite_teachers
UNION ALL SELECT 'Onsite Teachers hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'onsite_teacher'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Onsite Teachers hired', NULL
UNION ALL SELECT 'Translators', created_at
FROM translators
UNION ALL SELECT 'Translators hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'translator'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Translators hired', NULL
UNION ALL SELECT 'Interpreters', created_at
FROM interpreters
UNION ALL SELECT 'Interpreters hired', created_at
FROM purchases
INNER JOIN purchased_profiles
ON purchased_profiles.purchase_id = purchases.id
AND purchased_profiles.profile_type = 'interpreter'
WHERE purchases.transaction_status = 'completed'
UNION ALL SELECT 'Interpreters hired', NULL;