2015-02-23 78 views
0

我有这个DB结构mySQL SELECT帮助。 IF还是EXISTS?

* user 
user_id 
name 

* client 
client_id 
name 

* user_client 
user_client_id 
user_id 
client_id 

* message 
message_id 
client_id 
description 

如果对user_client条目则用户仅限于为他的表ID列出的特定的客户端权限。如果没有条目,则用户可以访问任何客户端。

如何只选择用户可以阅读的邮件?

我想在WHERE子句上做一个IF来检查user_client表上是否有条目,但我不知道该从哪里去。如果user_client上没有条目,或者只有user_client上指定的client_id,则需要选择来自任何客户端的所有消息。表

感谢您的帮助!

+0

您能否显示您正在尝试修复的查询? – Alex 2015-02-23 17:37:08

+0

你在这里?你会回答我的问题吗?并显示预期的结果? – Alex 2015-02-23 18:23:57

+0

嗨,亚历克斯!刚刚看到你的消息。我没有完成查询,因为我意识到正在走错方向,我错过了一些东西。但是,这是我有什么: 选择 \t \t \t message.message_id, \t \t \t message.description \t \t FROM \t \t \t消息 \t \t WHERE \t \t \t discussionMessage.insertWhen> = DATE_SUB(NOW( ),INTERVAL 5 MINUTE) \t \t \t AND \t \t \t IF((SELECT COUNT(1)FROM user_client WHERE USER_ID = user.user_id)> = 1 \t \t \t \t \t \t message.clientId IN( \t \t \t \t SELECT \t \t \t \t \t CLIENT_ID \t \t \t \t FROM \t \t \t \t \t user_client \t \t \t \t WHERE \t \t \t \t \t user_client.userId = {} USERIDHERE \t \t \t),) – Kitara 2015-02-23 18:37:24

回答

0

我会建议做两个不同的查询:一个用于超级用户另一个用于限制用户。然后你可以用UNION加入这两个结果。

SELECT M.message_id, 
      M.client_id, 
      M.description 
     FROM message M 
INNER JOIN user_client UC ON (UC.client_id = M.client_id) 
INNER JOIN user U ON (UC.user_id = U.id) 
    WHERE U.id = :user_id 

    UNION 

    SELECT M.message_id, 
      M.client_id, 
      M.description 
     FROM message M 
    WHERE NOT EXISTS ( 
       SELECT * 
       FROM user_client 
       WHERE user_id = :user_id 
      ) 

您可以获得与其他查询相同的结果,但恕我直言,这一个更清晰,更易于维护。

编辑:如果你想确保用户存在,你应该加入用户表的第二个查询。

SELECT M.message_id, 
      M.client_id, 
      M.description 
     FROM message M 
     JOIN user U 
    WHERE U.id = :user_id 
     AND NOT EXISTS ( 
       SELECT * 
       FROM user_client 
       WHERE user_id = :user_id 
      ) 
+0

霍尔迪嗨!我能够使用您的查询使其在我身边工作!谢谢,我一直在完成,并会在我做所有测试时立即被接受为答案。 – Kitara 2015-02-23 18:39:43

+0

谢谢。请记住,如果你传递一个不存在的:user_id,它将返回所有的消息。您可以在调用查询之前确保用户存在,或者修改联合的第二部分以检查用户是否存在。 – 2015-02-23 18:49:45

+0

Hi @ jordi-llull它的工作原理,我刚刚看到你发送的关于返回所有消息的消息,如果用户不存在,我应该使用mysql查询来验证它,如果返回的行数大于零,它会调用消息查询或您的消息意味着什么,是否可以添加到查询中? – Kitara 2015-02-23 19:33:48

0

这样做的一种方式可能是使用两个不同的查询来创建一组用户可以根据需要查看和过滤的消息;这样的事情应该工作:

存在于user_client表
select * from (
    select u.user_id, u.name, c.name client, m.message_id, m.description 
    from user u 
    join user_client uc on u.user_id = uc.user_id 
    join client c on uc.client_id = c.client_id 
    join message m on c.client_id = m.client_id 
    union all 
    select u.user_id, u.name, c.name client, m.message_id, m.description 
    from user u 
    cross join client c 
    join message m on c.client_id = m.client_id 
    where user_id not in (select user_id from user_client) 
) x 
where x.user_id = 1; 

这里用户被限制在一组,他们有机会获得(在联盟第一组)的消息,而用户在user_client表不存在时,查看所有消息(联合中的第二组)。

Sample SQL Fiddle

0

如果我理解正确你的问题,如

1)管理用户......他们可以看看一切,因为他们将不得不在user_client表中没有记录。

2)客户主管......这样的主要责任人是特定的客户(或多个客户)。因此,用户在user_client表中有一个记录。如果是这样,那么只允许用户查看他们与之关联的客户的记录。

select 
     m.message_id, 
     m.client_id, 
     m.description, 
     c.name as clientName 
    from 
     (select count(*) as HasClients 
      from user_client 
      where user_id = TheUserYouWant) ClientCheck, 
     message m 
     left join user_client uc 
      on m.client_id = uc.client_id 
      AND uc.user_id = TheUserYouWant 
     join client c 
      on m.client_id = c.client_id 
    where 
     ClientCheck.HasClients = 0 
     OR NOT uc.user_id IS NULL 

该查询查看user_client表TWICE。第一次只是对给定用户存在的那些记录进行计数,而不管与哪个客户端关联。查询将总是返回1行,它将为0(无此类记录),或者大于1(无论它们与多少个记录相关联)。

第二个实例是左连接到user_client表,只是在情况下,人员被限制为仅查看他们自己的客户端消息。

WHERE子句现在进入并说...如果客户端的基础计数为零,那么可以给我所有的消息。如果有任何其他值,则user_client表中的用户标识(作为客户和用户所需的消息的左连接)必须为EXIST(通过非user_id列的NULL值)。

现在,您可能不希望查询EVERY消息,因为它可能会随着数据库的增长而变得相当大,但是您可以在WHERE子句中添加任何其他条件,例如日期限制和/或客户端,你有兴趣