3

我有两张桌子。假设一个有操作列表(我工作的原始表有一个发送和接收的消息列表),另一个是用户表,其中包含用户的全名。我已经复制了我现在所拥有的问题。

在操作表(消息表)中找到的用户可能不存在于用户表中。我正在使用子查询来针对操作表的原始查询中的用户名选择用户的全名。当用户表中不存在操作表中的用户时,MySQL 返回NULL,这是预期的。但相反,我希望它返回原始用户名。

比如说,praveen用户表和操作表中是否都有。所以,我得到这样的东西:Praveen Kumar likes something.。说,我有另一个用户名,bluff它不存在于 users 表中,并且操作变成了这样:NULL shares something.. 在这里而不是NULL,是否可以返回用户名本身,例如bluff shares something.

此处提供了我的SQL Fiddle、架构详细信息和其他参考资料。让我知道我是否可以以更好的方式做到这一点。谢谢。

MySQL 5.5.30 模式设置

CREATE TABLE `users`
    (`username` varchar(15), `fullname` varchar(15))
;

INSERT INTO `users`
    (`username`, `fullname`)
VALUES
    ('praveen', 'Praveen Kumar'),
    ('jeff', 'Jeff Atwood')
;

CREATE TABLE `actions`
    (`user` varchar(7), `action` varchar(7))
;

INSERT INTO `actions`
    (`user`, `action`)
VALUES
    ('praveen', 'Like'),
    ('jeff', 'Comment'),
    ('praveen', 'Answer'),
    ('praveen', 'Share'),
    ('jeff', 'Comment'),
    ('bluff', 'Share'),
    ('jeff', 'Like')
;

询问

SELECT *, (
  SELECT `fullname` FROM `users` WHERE `user` = `username`
) AS `name` FROM `actions`

结果

+---------+---------+---------------+
| USER    | ACTION  | NAME          |
+---------+---------+---------------+
| praveen |    Like | Praveen Kumar |
|    jeff | Comment | Jeff Atwood   |
| praveen |  Answer | Praveen Kumar |
| praveen |   Share | Praveen Kumar |
|    jeff | Comment | Jeff Atwood   |
|   bluff |   Share | (null)        |
|    jeff |    Like | Jeff Atwood   |
+---------+---------+---------------+

预期产出

+---------+---------+---------------+
| USER    | ACTION  | NAME          |
+---------+---------+---------------+
| praveen |    Like | Praveen Kumar |
|    jeff | Comment | Jeff Atwood   |
| praveen |  Answer | Praveen Kumar |
| praveen |   Share | Praveen Kumar |
|    jeff | Comment | Jeff Atwood   |
|   bluff |   Share | bluff         |
|    jeff |    Like | Jeff Atwood   |
+---------+---------+---------------+
4

3 回答 3

3

你可以像这样使用LEFT JOINwithCASE语句:

SELECT User, Action 
       ,CASE WHEN Fullname IS NULL 
             THEN User 
             ELSE Fullname 
              END as Name
FROM actions a
LEFT JOIN users u
ON a.User = u.username;

输出

|    USER |  ACTION |          NAME |
-------------------------------------
| praveen |    Like | Praveen Kumar |
|    jeff | Comment |   Jeff Atwood |
| praveen |  Answer | Praveen Kumar |
| praveen |   Share | Praveen Kumar |
|    jeff | Comment |   Jeff Atwood |
|   bluff |   Share |         bluff |
|    jeff |    Like |   Jeff Atwood |

看到这个 SQLFiddle

于 2013-04-24T12:14:49.460 回答
3

利用IFNULL

SELECT *, IFNULL((
  SELECT `fullname` FROM `users` WHERE `user` = `username`
),`user`) AS `name` FROM `actions`

SQLFiddle

编辑:

COALESCE做同样的事情

SELECT *, COALESCE((
  SELECT `fullname` FROM `users` WHERE `user` = `username`
),`user`) AS `name` FROM `actions`
于 2013-04-24T12:12:52.343 回答
0

感谢接受的答案,我在我的生产代码中使用了这个,性能非常好。注意 LIMIT 1 的 mysql 用法(类似于 sql server 的 SELECT TOP 1)。并注意COALESCE和CONCAT的组合用法,即如果郊区为null,则不附加额外的逗号,因为',' + null = null,然后使用coalesce然后变成空字符串。

SELECT 
    COALESCE((SELECT Customer.Name From Customer WHERE Quote.CustomerId = Customer.Id LIMIT 1), '') As CustomerName, 
    Description, 
    (CONCAT(COALESCE(DeliveryStreet, ''), COALESCE(CONCAT(', ', DeliverySuburb), ''), COALESCE(CONCAT(', ', DeliveryCity), ''), COALESCE(CONCAT(', ', DeliveryPostcode), ''))) as DeliveryAddress, 
    COALESCE(DATE_FORMAT(CreatedDate, '%d %b %y'), '') as QuoteCreatedDate, 
    COALESCE((SELECT User.Name FROM QuoteStatusHistory INNER JOIN Status ON Status.Id = QuoteStatusHistory.StatusId INNER JOIN User ON QuoteStatusHistory.UserId = User.Id WHERE QuoteStatusHistory.QuoteId = Quote.Id AND QuoteStatusHistory.StatusId = 1 ORDER BY QuoteStatusHistory.CreatedDate DESC LIMIT 1), '') as CreatedBy, 
    COALESCE((SELECT DATE_FORMAT(QuoteStatusHistory.CreatedDate, '%d %b %y') FROM QuoteStatusHistory WHERE QuoteStatusHistory.QuoteId = Quote.Id AND QuoteStatusHistory.StatusId = 2 ORDER BY QuoteStatusHistory.CreatedDate DESC LIMIT 1), '') as OrderDate, 
    COALESCE((SELECT User.Name FROM QuoteStatusHistory INNER JOIN Status ON Status.Id = QuoteStatusHistory.StatusId INNER JOIN User ON QuoteStatusHistory.UserId = User.Id WHERE QuoteStatusHistory.QuoteId = Quote.Id AND QuoteStatusHistory.StatusId = 2 ORDER BY QuoteStatusHistory.CreatedDate DESC LIMIT 1), '') as OrderedBy, 
    COALESCE((SELECT DATE_FORMAT(QuoteStatusHistory.CreatedDate, '%d %b %y') FROM QuoteStatusHistory WHERE QuoteStatusHistory.QuoteId = Quote.Id AND QuoteStatusHistory.StatusId IN (3, 4) ORDER BY QuoteStatusHistory.CreatedDate DESC LIMIT 1), '') as DispatchDate, 
    QuotePrice,
    COALESCE((SELECT Status.Name FROM QuoteStatusHistory INNER JOIN Status ON Status.Id = QuoteStatusHistory.StatusId WHERE QuoteStatusHistory.QuoteId = Quote.Id ORDER BY QuoteStatusHistory.CreatedDate DESC LIMIT 1), '') as QuoteStatus 
FROM Quote
于 2019-07-07T05:38:13.573 回答