SQL - 根据值拆分列
SQL - Splitting a column based on the values
我正在尝试根据列中的值将结果集中的列拆分为 2 列。
因此,一个用户可以订阅多个项目,并且该用户可以有 2 个可以接收此订阅的电子邮件地址。
结果集给出了订阅列表及其对应的订阅电子邮件 ID 条目。
数据库详细信息
Table 1 - user_subscriptions
user_id
email_id - 1 for email id 1 and 2 for email id 2
subscription_id
Table 2 - subscriptions
subscription_id
subscription_name
现在我需要用户的所有订阅,无论是否通过任一电子邮件 ID 订阅。
所以我得到了这样的结果集
+----------------------+----------+
| subscription_name | email_id |
+----------------------+----------+
| item1 | 1 |
| item1 | 2 |
| item2 | null |
| item3 | 1 |
| item4 | null |
| item5 | 2 |
+----------------------+----------+
所以我想将上面的结果集拆分成如下的内容
+-------------------+---------+---------+
| subscription_name | email_1 | email_2 |
+-------------------+---------+---------+
| item1 | 1 or Y | 1 or Y |
| item2 | 0 or N | 0 |
| item3 | 1 | 0 |
| item4 | 0 | 0 |
| item5 | 0 | 1 |
+-------------------+---------+---------+
希望这个问题是有道理的。如有任何帮助,我们将不胜感激!
已更新------------
示例数据:
subscriptions -
+-----------------+-------------------+
| subscription_id | subscription_name |
+-----------------+-------------------+
| 1 | item1 |
| 2 | item2 |
| 3 | item3 |
| 4 | item4 |
| 5 | item5 |
+-----------------+-------------------+
user_subscriptions
+---------+----------+-----------------+
| user_id | email_id | subscription_id |
+---------+----------+-----------------+
| 101 | 1 | 1 |
| 101 | 2 | 1 |
| 101 | 1 | 3 |
| 101 | 2 | 5 |
| 102 | 1 | 1 |
| 102 | 2 | 1 |
+---------+----------+-----------------+
预期结果:
对于user_id = 101
+-----------------+-------------------+--------+--------+
| subscription_id | subscription_name | mail_1 | mail_2 |
+-----------------+-------------------+--------+--------+
| 1 | item1 | Y | Y |
| 2 | item2 | N | N |
| 3 | item3 | Y | N |
| 4 | item4 | N | N |
| 5 | item5 | N | Y |
+-----------------+-------------------+--------+--------+
您需要一个条件聚合:
select us.subscription_name,
-- there's at least one email
CASE WHEN MIN(us.email_id) IS NOT NULL THEN 'Y' ELSE 'N' END as email_1,
-- there's more than one email
CASE WHEN MIN(us.email_id) <> MAX(us.email_id) THEN 'Y' ELSE 'N' END as email_2
from subscriptions as s
left join user_subscriptions as us
on s.subscription_id = us.subscription_id
where us.user_id = ...
group by us.subscription_name
SELECT
S.subscription_id,
S.subscription_name,
CASE
WHEN US1.mail_ID IS NULL THEN 'N'
ELSE 'Y'
END mail_1,
CASE
WHEN US2.mail_ID IS NULL THEN 'N'
ELSE 'Y'
END mail_2
FROM subscriptions S
LEFT JOIN user_subscriptions US1
ON S.subscription_id = US1.subscription_id
AND US1.mail_id = 1
LEFT JOIN user_subscriptions US2
ON S.subscription_id = US2.subscription_id
AND US2.mail_id = 2
WHERE us1.user_id = 5 -- or use a variable @user_ID
OR us2.user_id = 5
我以前没有在 sybase 工作过,但我很确定以下 SQL 会很容易翻译(甚至 运行 直接翻译):
SELECT
s.subscription_name,
COUNT(email_1.subscription_id) AS email_1,
COUNT(email_2.subscription_id) AS email_2
FROM subscriptions AS s
LEFT JOIN user_subscriptions AS email_1 ON (
s.subscription_id = email_1.subscription_id AND
email_1.email_id = 1
)
LEFT JOIN user_subscriptions AS email_2 ON (
s.subscription_id = email_2.subscription_id AND
email_2.email_id = 2
)
;
你也可以在 SELECT
中说 IF(email_1.subscription_id IS NOT NULL, 'Y', 'N')
等到 return 直接 yes/no 而不是计数等
它的工作原理是 LEFT JOIN
语句列表将匹配任何 "user subscription" 记录 email_id=1
和 email_id=2
等
我缺乏 sybase 知识免责声明: ANSI SQL 无法执行 PIVOT
- 如果 sybase 可以,您可以更优雅地执行此操作我确定。还有另一个问题+答案暗示sybase可以做这样的事情;值得你去看看:
希望对您有所帮助!
我正在尝试根据列中的值将结果集中的列拆分为 2 列。 因此,一个用户可以订阅多个项目,并且该用户可以有 2 个可以接收此订阅的电子邮件地址。 结果集给出了订阅列表及其对应的订阅电子邮件 ID 条目。
数据库详细信息
Table 1 - user_subscriptions
user_id
email_id - 1 for email id 1 and 2 for email id 2
subscription_id
Table 2 - subscriptions
subscription_id
subscription_name
现在我需要用户的所有订阅,无论是否通过任一电子邮件 ID 订阅。 所以我得到了这样的结果集
+----------------------+----------+
| subscription_name | email_id |
+----------------------+----------+
| item1 | 1 |
| item1 | 2 |
| item2 | null |
| item3 | 1 |
| item4 | null |
| item5 | 2 |
+----------------------+----------+
所以我想将上面的结果集拆分成如下的内容
+-------------------+---------+---------+
| subscription_name | email_1 | email_2 |
+-------------------+---------+---------+
| item1 | 1 or Y | 1 or Y |
| item2 | 0 or N | 0 |
| item3 | 1 | 0 |
| item4 | 0 | 0 |
| item5 | 0 | 1 |
+-------------------+---------+---------+
希望这个问题是有道理的。如有任何帮助,我们将不胜感激!
已更新------------
示例数据:
subscriptions -
+-----------------+-------------------+
| subscription_id | subscription_name |
+-----------------+-------------------+
| 1 | item1 |
| 2 | item2 |
| 3 | item3 |
| 4 | item4 |
| 5 | item5 |
+-----------------+-------------------+
user_subscriptions
+---------+----------+-----------------+
| user_id | email_id | subscription_id |
+---------+----------+-----------------+
| 101 | 1 | 1 |
| 101 | 2 | 1 |
| 101 | 1 | 3 |
| 101 | 2 | 5 |
| 102 | 1 | 1 |
| 102 | 2 | 1 |
+---------+----------+-----------------+
预期结果:
对于user_id = 101
+-----------------+-------------------+--------+--------+
| subscription_id | subscription_name | mail_1 | mail_2 |
+-----------------+-------------------+--------+--------+
| 1 | item1 | Y | Y |
| 2 | item2 | N | N |
| 3 | item3 | Y | N |
| 4 | item4 | N | N |
| 5 | item5 | N | Y |
+-----------------+-------------------+--------+--------+
您需要一个条件聚合:
select us.subscription_name,
-- there's at least one email
CASE WHEN MIN(us.email_id) IS NOT NULL THEN 'Y' ELSE 'N' END as email_1,
-- there's more than one email
CASE WHEN MIN(us.email_id) <> MAX(us.email_id) THEN 'Y' ELSE 'N' END as email_2
from subscriptions as s
left join user_subscriptions as us
on s.subscription_id = us.subscription_id
where us.user_id = ...
group by us.subscription_name
SELECT
S.subscription_id,
S.subscription_name,
CASE
WHEN US1.mail_ID IS NULL THEN 'N'
ELSE 'Y'
END mail_1,
CASE
WHEN US2.mail_ID IS NULL THEN 'N'
ELSE 'Y'
END mail_2
FROM subscriptions S
LEFT JOIN user_subscriptions US1
ON S.subscription_id = US1.subscription_id
AND US1.mail_id = 1
LEFT JOIN user_subscriptions US2
ON S.subscription_id = US2.subscription_id
AND US2.mail_id = 2
WHERE us1.user_id = 5 -- or use a variable @user_ID
OR us2.user_id = 5
我以前没有在 sybase 工作过,但我很确定以下 SQL 会很容易翻译(甚至 运行 直接翻译):
SELECT
s.subscription_name,
COUNT(email_1.subscription_id) AS email_1,
COUNT(email_2.subscription_id) AS email_2
FROM subscriptions AS s
LEFT JOIN user_subscriptions AS email_1 ON (
s.subscription_id = email_1.subscription_id AND
email_1.email_id = 1
)
LEFT JOIN user_subscriptions AS email_2 ON (
s.subscription_id = email_2.subscription_id AND
email_2.email_id = 2
)
;
你也可以在 SELECT
中说 IF(email_1.subscription_id IS NOT NULL, 'Y', 'N')
等到 return 直接 yes/no 而不是计数等
它的工作原理是 LEFT JOIN
语句列表将匹配任何 "user subscription" 记录 email_id=1
和 email_id=2
等
我缺乏 sybase 知识免责声明: ANSI SQL 无法执行 PIVOT
- 如果 sybase 可以,您可以更优雅地执行此操作我确定。还有另一个问题+答案暗示sybase可以做这样的事情;值得你去看看:
希望对您有所帮助!