通过在特定条件下添加具有特定值的字段从两个表中进行选择

时间:2019-01-24 21:25:00

标签: mysql sql

Table1: Students
ID              Name        EternalToken
200901212       Joe         xxxxxx
200809922       David       yyyyyy
201009122       Chris       zzzzzz

Table2: Banned
ID      StudentID
1       200901212

我想选择所有学生,并显示一个附加字段,该学生通过隐藏EternalToken来表明该学生已被禁止

SELECT * FROM Students s 
LEFT JOIN Banned b
ON s.ID = b.StudentID

这将同时显示两个表。但是,我希望结果是这样的:

ID              Name        EternalToken    Banned
200901212       Joe         NULL            1
200809922       David       yyyyyy          0
201009122       Chris       zzzzzz          0

只有被禁止的学生才应该有EternalToken = NULL

请注意,这只是我要实现的目标的一个示例,并不完全是我在做什么。 学生和被禁止的只是一个例子,我知道这不是多对多的关系,所以我只能在一张桌子上就可以做到。但是从技术上回答这个问题将极大地帮助我实现灵活的解决方案。

2 个答案:

答案 0 :(得分:1)

您可以使用以下查询:

SELECT
    s.ID,
    s.Name,
    CASE WHEN b.StudentID IS NOT NULL THEN NULL ELSE s.EternalToken END AS EternalToken,
    CASE WHEN b.StudentID IS NULL THEN 0 ELSE 1 END AS Banned
FROM Students s
LEFT JOIN Banned b
    ON s.ID = b.StudentID;

enter image description here

Demo

请注意,这与COALESCE函数的作用相反。 COALESCE检查一个值,如果该值为NULL,则返回一个备用值。上面用于令牌的CASE表达式检查值是否为 not NULL,并在这种情况下返回NULL,否则将显示永恒的令牌值。

答案 1 :(得分:0)

使用caseexists

SELECT s.*,
       (CASE WHEN EXISTS (SELECT 1 FROM banned b WHERE s.ID = b.StudentID)
             THEN 1 ELSE 0
        END) as is_banned
FROM Students s ;

在MySQL中,您实际上可以将其简化为:

SELECT s.*,
       ( EXISTS (SELECT 1 FROM banned b WHERE s.ID = b.StudentID) ) as is_banned
FROM Students s ;

EXISTS方法相比,我更喜欢LEFT JOIN,因为逻辑清楚地表明不会添加任何行。当LEFT JOIN中有重复项时,banned将使行数相乘。