如何使用连接实现/改进/加快此查询的速度

时间:2015-03-24 07:26:16

标签: sql sqlite

请耐心等待我,我不擅长SQL:

我有三张桌子

1)通知 - 存储我的所有数据

2)GroupTable - 具有组名和相关ID

3)GroupUser - 此表将Uname和Udob映射到GroupTable中的一个组。

现在,在我从Notifications中获取记录之前,我想检查GroupTable for GroupID取这个GroupID并在GroupUser中查找此GroupID中的所有记录(Names,DOB,因为它们是唯一的)一旦我得到这些数据,我想要获取名称和DOB的通知表中的记录按日期的升序排列:

到目前为止,我有以下查询,它只是我感到不满意,我认为这可以改进:

 SELECT 
    * 
 FROM 
   (SELECT 
        * 
    FROM Notifications 
    WHERE 
          DateToNotify < '2016-03-24' AND 
          NotificationDateFor IN 
                (SELECT gu.Name 
                 FROM GroupUser AS gu 
                 INNER JOIN GroupTable AS gt ON 
                               gu.GroupID = gt._id  AND
                               gt.GroupName = "Groupn"
                ) AND
          DOB IN 
                (SELECT gu.DOB 
                 FROM GroupUser AS gu 
                 INNER JOIN GroupTable AS gt ON 
                               gu.GroupID = gt._id AND 
                               gt.GroupName = "Groupn"
                )
     ) as T 

 ORDER BY 
      SUBSTR(DATE('NOW'), 0) > SUBSTR(DateToNotify, 0)
    , SUBSTR(DateToNotify, 0)

1 个答案:

答案 0 :(得分:1)

我认为你不会用连接而不是IN子句来加快速度。重写可能甚至不会改变执行计划,因为dbms无论如何都试图以最佳方式访问数据。

有些奇怪的是,您不会查找与name和dob匹配的组用户,但只能确保有与该名称匹配的组用户以及 - 可能是其他 - 与dob匹配的组用户。但正如你所说的那样,查询工作正常,好的。

编辑:好的,根据您的评论,您实际上希望在 名称和dob上进行groupuser匹配。所以你要找的是

AND (NotificationDateFor, DOB) IN (SELECT gu.Name, gu.DOB FROM ...)

但SQLite不支持这种漂亮的语法(Oracle是我所知道的唯一的dbms)。

所以你加入或使用EXISTS。

加入:

select distinct n.*
from notifications n
join
(
  select name, dob 
  from groupuser
  where groupid = (select _id from grouptable where groupname = 'groupn')
) as gu on n.notificationdatefor = gu.name and n.dob = gu.dob
where n.datetonotify < '2016-03-24'
order by date('now') > n.datetonotify, n.datetonotify;

使用EXISTS:

select *
from notifications n
where datetonotify < '2016-03-24'
and exists
(
  select *
  from groupuser gu
  where gu.groupid = (select _id from grouptable where groupname = 'groupn')
  and gu.name = n.notificationdatefor
  and gu.dob = n.dob
)
order by date('now') > n.datetonotify, n.datetonotify;