使用LEFT JOIN和CASE语句的SQL查询

9

这是我的两个表的示例。

enter image description here

问题: 如何使用左连接创建SQL查询?

下面是具体情况:

正如我之前所说,我有两个表(TABLE1和TABLE2), 我尝试使用左连接将两个表中的UserID合并到一个表中。

以下是代码:

select * from table1 a left join table2 on a.userid = b.userid

现在两个表已经合并了。

我需要做的是:
如果状态为全部完成,则显示“已完成”
如果状态包含完成和未完成,则显示“未完成”
否则显示“无状态”

它应该看起来像这样。

enter image description here

注意:
由于UserID = 1(table1)包含完成和未完成状态(table2)
因此它会显示'未完成'(新列)

由于UserID = 4(table1)包含全部完成状态(table2)
所以它会显示'已完成'(新列)

-----------------------------------

如果我将状态更改为整数会怎么样?

enter image description here

同样的过程。谢谢


2
叹气。你为什么想要这个?你应该在应用程序层面上完成这个。 - Kermit
那要取决于很多因素,我认为这是相当有效的。 - flup
你的第二个例子似乎有误。第7行不应该写成“不完整”吗? - Robert Harvey
请将以下与程序相关的内容从英语翻译成中文。仅返回已翻译的文本:因为您可以在表二中看到,userid = 4 包含“完成”状态。 - StackOverflowUser
能否在SQL查询中实现?我真的不知道该怎么做。 - StackOverflowUser
3个回答

13
SELECT  a.*, 
        CASE WHEN b.totalCount = 1 AND b.totalINC = 0 THEN 'Complete'
             WHEN totalCount IS NULL THEN ''
             ELSE 'Incomplete'
        END STatus
FROM    table1 a
        LEFT JOIN
        (
            SELECT  UserID, 
                    COUNT(DISTINCT STATUS) totalCount,
                    SUM(CASE WHEN status = 'Incomplete' THEN 1 ELSE 0 END) totalINC
            FROM table2
            GROUP BY UserID
        ) b ON a.UserID = b.UserID

更新1

您需要更改的唯一内容是CASE语句

SELECT  a.*, 
        CASE WHEN b.totalCount = 1 AND b.totalINC = 0 THEN 'Complete'
             WHEN totalCount IS NULL THEN ''
             ELSE 'Incomplete'
        END STatus
FROM    table1 a
        LEFT JOIN
        (
            SELECT  UserID, 
                    COUNT(DISTINCT STATUS) totalCount,
                    SUM(CASE WHEN status <> 100 THEN 1 ELSE 0 END) totalINC
            FROM table2
            GROUP BY UserID
        ) b ON a.UserID = b.UserID;

但是如果状态更改为整数呢?请看更新的问题 - StackOverflowUser
1
你需要更改查询语句中的CASE语句,SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) totalINC中的2代表未完成。 - John Woo
它计算您状态的不同数量,如果您只有一种类型的状态,则返回1,否则返回2或更多其他类型。如果userID没有现有值,则还将返回null。 - John Woo

5

简单但棘手的解决方案:

对于数据库来说,INCOMPLETE大于COMPLETE,因此您可以简单地执行以下操作:

SELECT a.UserID, 
  LOWER(COALESCE(MAX(b.status) , 'NO STATUS'))
  FROM table1 a 
 LEFT JOIN table2 b on a.userid = b.userid
 GROUP BY a.UserID

SqlFiddle(包括Andomar的更好解决方案)

该网站为SqlFiddle,可以让你在线运行SQL代码并查看结果。其中还包括Andomar提供的更优秀的解决方案。

2
+1 为了这个诡计,不过如果状态被翻译的话会导致一个相当棘手的 bug。 - Andomar
@Andomar 完全同意,并且赞同你的“正确但令人烦恼”的解决方案 +1 ;) - Raphaël Althaus
@gean08 你可以谷歌一下:这是一个 ANSI SQL 函数,它的作用是:如果第一个参数的值为 null,则取第二个参数的值(如果第二个参数也为 null,则取第三个参数的值,以此类推)。在这种情况下,MAX(NULL) = null,因此如果对于表 a 的用户在 table2 中没有任何内容,它将返回“NO STATUS”。 - Raphaël Althaus

3
select  a.UserID
,       case
        when sum(case when b.status = 'Incomplete' then 1 end) > 0 
            then 'Incomplete' 
        when sum(case when b.status = 'Complete' then 1 end) > 0 
            then 'Complete' 
        else 'No Status' 
        end
from    table1 a 
left join 
        table2 b
on      a.userid = b.userid
group by
        a.UserID

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接