SELF-JOIN丢弃真正的CROSS JOIN行

时间:2016-06-14 14:04:41

标签: sql mariadb self-join cross-join

我有以下查询;

我得到的是门票信息。我使用自联接来获取同一行中的请求者和受让人:

SELECT z.id AS TICKET, z.name AS Subject, reqs.name AS Requester, techs.name AS Assignee,
       e.name AS Entity,DATE_FORMAT(tt.date,'%y%-%m%-%d') AS DATE,
       DATE_FORMAT(tt.date,'%T') AS HOUR,
       CASE WHEN z.priority = 6 THEN 'Mayor' WHEN z.priority = 5 THEN 'Muy urgente' WHEN z.priority = 4 THEN 'Urgente'WHEN z.priority = 3 THEN 'Mediana' WHEN z.priority = 2 THEN 'Baja' WHEN z.priority =1 THEN 'Muy baja' END AS Priority,
       c.name AS Category, i.name AS Department
FROM glpi_tickets_users tureq
JOIN glpi_tickets_users tutech ON  tureq.tickets_id = tutech.tickets_id
JOIN glpi_users AS reqs  ON tureq.users_id = reqs.id
JOIN glpi_users AS techs ON tutech.users_id = techs.id
JOIN glpi_tickets z ON z.id = tureq.tickets_id
LEFT OUTER JOIN glpi_tickettasks tt ON z.id = tt.tickets_id
LEFT JOIN glpi_itilcategories i ON z.itilcategories_id = i.id
LEFT JOIN glpi_usercategories c ON c.id = reqs.usercategories_id
INNER JOIN glpi_entities e ON z.entities_id = e.id
WHERE (tureq.id < tutech.id AND tureq.type < tutech.type) OR
      (tureq.id < tutech.id AND tureq.users_id = tutech.users_id) OR
      (tureq.id = tutech.id AND tureq.users_id = tutech.users_id)

问题是我得到了类似的东西:

1   Report jdoe        jdoe        Development   16-06-07  11:56:17        Mediana Software    Mkt
1   Report jdoe        fwilson     Development   16-06-07  11:56:17        Mediana Software    MKt
1   Report fwilson     fwilson     Development   16-06-07  11:56:17        Mediana Software    Mkt
2   Task11 gwilliams   gwilliams   Ops           16-06-08  12:00:00        ALTA    Hardware    Def
3   Task12 gwilliams   gwilliams   Ops           16-06-08  12:01:00        ALTA    Hardware    Def

我不想要第一行和第三行,因为它是一个CROSS JOIN结果。第二行是可以的,因为jdoe是请求者而fwilson是受让人。

问题在于,有时请求者和受让人是相同的,例如:他为自己将要完成的任务创建一张票。例如,第4行和第5行都可以。

那么,我该怎样做才能为那些不同的案例做出改变,即:我需要包括:

tureq.id = tech.id AND req.users_id = tech.users.id

但是如果已经存在则 tureq.id = tech.id AND req.users_id <> tech.users_id

更新

主要问题是用户可以为自己分配一张票:

 SELECT * from glpi_tickets_users WHERE type = 2  GROUP BY tickets_id HAVING COUNT(users_id)<2 limit 3;
+----+------------+----------+------+------------------+-------------------+
| id | tickets_id | users_id | type | use_notification | alternative_email |
+----+------------+----------+------+------------------+-------------------+
|  1 |          2 |       12 |    2 |                1 | NULL              |
|  3 |          6 |       13 |    2 |                1 | NULL              |
|  7 |          8 |       14 |    2 |                1 | NULL              |
+----+------------+----------+------+------------------+-------------------+

更新2:

这是一个人为错误。问题实际上不是关于自我指定的门票。相反,要么某些门票没有请求者或者有请求者,但仍然没有分配任何解析器。 我找到了

2 个答案:

答案 0 :(得分:3)

由于您感兴趣的每张票总有两种类型,您只需选择相应的记录即可获得每张票的请求者和受让人。

select 
  t.id as ticket, 
  t.name as subject, 
  requester.name as requester, 
  assignee.name as assignee,
  e.name as entity,
  date_format(tt.date,'%y%-%m%-%d') as date,
  date_format(tt.date,'%T') as hour,
  case t.priority 
    when 6 then 'Mayor' 
    when 5 then 'Muy urgente' 
    when 4 then 'Urgente'
    when 3 then 'Mediana' 
    when 2 then 'Baja' 
    when 1 then 'Muy baja'
  end as priority,
  uc.name as category,
  ic.name as department
from glpi_tickets t
join glpi_entities e on e.id = t.entities_id
join 
(
  select tu.tickets_id, u.name, u.usercategories_id 
  from glpi_tickets_users tu
  join glpi_users u on u.id = users_id
  where tu.type = 1
) requester on requester.tickets_id = t.id
join 
(
  select tu.tickets_id, u.name 
  from glpi_tickets_users tu
  join glpi_users u on u.id = users_id
  where tu.type = 2
) assignee on assignee.tickets_id = t.id
left join glpi_itilcategories ic on ic.id = t.itilcategories_id
left join glpi_usercategories uc on uc.id = requester.usercategories_id;
left outer join glpi_tickettasks tt on tt.tickets_id = t.id

我唯一想知道的是:每张票可以有多个票务任务。那么你想做什么呢?结果中每个票证任务有一行吗?这就是查询的作用。只是,看起来您的结果行不包含除日期之外的任务的任何信息,这看起来很奇怪,因此您可能有许多具有相同数据的行,只有不同的日期。所以,也许,你更愿意每张票的第一个或最后一个日期。要获取每张故障单的最后日期,您需要使用以下命令替换查询中的最后一行:

left outer join
(
  select tickets_id, max(date) as date
  from glpi_tickettasks
  group by tickets_id
) tt on tt.tickets_id = t.id

您可能想要添加ORDER BY子句。

答案 1 :(得分:0)

您需要为联接添加更多限定符,例如

JOIN glpi_tickets_users tutech ON  tureq.tickets_id = tutech.tickets_id and tutech.type = 2