使用连接优化postrgeSQL查询和" ghost"引用?

时间:2015-06-26 09:20:51

标签: sql database postgresql query-optimization

我做了这个查询以获取一些数据。

 select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type
 from ticket_history th, ticket_priority tp, ticket_state ts, users, queue, ticket_type tt, groups g
 where th.priority_id = tp.id
 AND queue.id = g.id
 AND th.state_id = ts.id
 AND owner_id = users.id
 AND th.queue_id = queue.id
 AND th.type_id = tt.id
 AND th.id > $lastUpdateId
 ORDER BY th.id desc

它运作得很好但是我有些抱怨这个查询很慢(抱怨'甚至没有费心去测试它)...但我决定用它来调整它一些INNER JOINS - 第一个问题:这是连接表的最有效方法,并避免重复主id(在本例中为ticket_history)吗?

我重构了查询,看起来像这样:

 select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type
 FROM ticket_history, groups
 INNER JOIN queue ON queue.id = groups.id
 INNER JOIN ticket_priority ON ticket_priority.id = ticket_history.priority_id
 INNER JOIN ticket_state ON ticket_state.id = ticket_history.state_id
 INNER JOIN users ON users.id = ticket_history.owner_id
 INNER JOIN queue ON queue.id = ticket_history.queue_id
 INNER JOIN ticket_type ON ticket_type.id = ticket_history.type_id
 WHERE th.id > 7352616
 ORDER BY th.id desc

但现在我收到了错误

    ERROR:  invalid reference to FROM-clause entry for table "ticket_history"
LINE 4: ...NER JOIN ticket_priority ON (ticket_priority.id = ticket_his...
                                                             ^
HINT:  There is an entry for table "ticket_history", but it cannot be referenced from this part of the query.
********** Error **********

ERROR: invalid reference to FROM-clause entry for table "ticket_history"
SQL state: 42P01
Hint: There is an entry for table "ticket_history", but it cannot be referenced from this part of the query.

这让我想到了第二个问题 - 这是什么意思?我需要引用ticket_history.priority_id ...

PS:我的目标是获取ticket_history中的数据,但不是拥有priority_id而是我想要实际的优先级文本等等(除了我真正想要的用户和组之外)他们的身份而不是名字。最棘手的部分是我在ticket_history中有队列ID,从队列表中我需要提取group_id,这是我真正需要的。

编辑:这是第一个查询的示例结果

id;  ticket_id;  priority;  state;  user_id;  group_id;  type    
7376618; 203123; "4 Low"; "closed"; 385; 22; "Service Request"
7376617; 201341; "3 Medium"; "closed"; 100; 21; "Problem"
7376616; 201230; "1 SuperDuperHigh"; "closed"; 150; 10; "Service Request"

查询从localhost实例返回19067秒(提供或获取)中的7360行。 原始表"原样"包含id而不是文本/数字。所以它包含" type_id"而不是类型。 group_id是从两个不同表之间的相关性中获取的组。它是ticket_history-> queue->组,所以它需要关联这些id以找到group_id

EDIT2:表格图如下(link) - 查找票证周围的表格 - 它是您能看到的最大的表格

2 个答案:

答案 0 :(得分:3)

From the documentation:

A JOIN clause combines two FROM items, which for convenience we will refer to as "tables", though in reality they can be any type of FROM item. Use parentheses if necessary to determine the order of nesting. In the absence of parentheses, JOINs nest left-to-right. In any case JOIN binds more tightly than the commas separating FROM-list items.

So the successive JOINs are relative to "groups", not "ticket_history". Flip the order of the tables to make it work:

SELECT th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id,
       g.id AS team_id, tt.name AS ticket_type
FROM ticket_history th
JOIN ticket_priority tp ON tp.id = th.priority_id
JOIN ticket_state ts ON ts.id = th.state_id
-- JOIN users ON users.id = th.owner_id   NOT USED IN THE QUERY
JOIN queue ON queue.id = th.queue_id
JOIN ticket_type tt ON tt.id = th.type_id
JOIN groups g ON g.id = queue.id
WHERE th.id > 7352616
ORDER BY th.id DESC;

Note that INNER before JOIN is a noise word; you can safely omit it.

答案 1 :(得分:1)

I think you can't reference ticket_history there, because you've got a comma between ticket_history and groups, so ticket_history is not part of all those inner joins. If I've understood your table structure correctly[it would be easier if you posted table defs and sample data BTW] I think this will work:

select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type
 FROM  groups
 INNER JOIN queue ON queue.id = groups.id
 -- include ticket_history with a join statement
INNER JOIN ticket_history ON queue.id = ticket_history.queue_id
     INNER JOIN ticket_priority ON ticket_priority.id = 
ticket_history.priority_id
 INNER JOIN ticket_state ON ticket_state.id = ticket_history.state_id
 INNER JOIN users ON users.id = ticket_history.owner_id

 INNER JOIN ticket_type ON ticket_type.id = ticket_history.type_id
 WHERE th.id > 7352616
 ORDER BY th.id desc