将SQL重写为JOINS而不是子查询

时间:2010-11-10 12:51:39

标签: sql mysql join subquery

我有一些麻烦将此查询重写为使用连接而不是两个子查询。如果你知道我的意思,我有一个解决它的问题。

SELECT o.order_id, n.title, c.first_name, t1.name, o.product_id,
    (SELECT ttd2.tid FROM term_data ttd2, term_node ttn2 WHERE ttd2.vid = 5 AND ttn2.nid = p.nid AND ttd2.tid=ttn2.tid) AS tid,
    (SELECT ttd4.name FROM term_data ttd4, term_node ttn4 WHERE ttd4.vid = 8 AND ttn4.nid = p.nid AND ttd4.tid=ttn4.tid) AS month
    FROM orders o, products p, node n, customers c, term_data t1, term_node t2
    WHERE o.product_id = p.nid
    AND p.nid = n.nid
    AND o.customer_email = c.customer_email
    AND t2.tid = t1.tid
    AND t1.vid = 6
    AND n.nid = t2.nid
你能帮忙吗?或者提供一些线索/提示。

3 个答案:

答案 0 :(得分:4)

使用ANSI SQL-92语法重写它(即使用JOIN和ON子句),它应该更加清晰。

现在,您的所有JOINWHERE条款混合在一起,因此很难看到关系。子查询不一定是个问题;一旦语法被清理,这应该变得更加清晰。

答案 1 :(得分:2)

通常:

SELECT ed列移至主SELECT语句,将FROM子句移至原始JOIN下方的FROM子句,并将将条件连接到该行。您的WHERE子句可以保持原样。

同样如@RedFilter所说,使用JOINON条款。我认为你在做笛卡尔,但由于语法的原因,我不确定。

例如(我不知道这对你的表结构是否有效,因为你没有给它):

SELECT o.order_id, n.title, c.first_name, t1.name, o.product_id,ttd2.tid as 'tid', ttd4.name as 'name'
FROM orders o
INNER JOIN products p ON o.product_id = p.nid
INNER JOIN node n ON AND p.nid = n.nid
INNER JOIN customers c ON o.customer_email = c.customer_email
INNER JOIN term_data t1 ON t2.tid = t1.tid
INNER JOIN term_node t2 ON n.nid = t2.nid 
INNER JOIN ...
WHERE n.nid = t2.nid
AND ttd2.vid = 5 
AND ttn2.nid = p.nid 
AND ttd2.tid=ttn2.tid)
AND t1.vid = 6
AND ...

答案 2 :(得分:2)

重写为使用ANSI-92 SQL并略微简化以删除冗余连接,您的查询应如下所示:

SELECT o.order_id, 
       n.title, 
       c.first_name, 
       tdv6.name, 
       o.product_id,
       tdv5.tid,
       tdv8.name    month
FROM orders o
     join products p           on o.product_id = p.nid
     join node n               on p.nid = n.nid
     join customers c          on o.customer_email = c.customer_email
     join term_node tnv        on n.nid = tn.nid
     join term_data tdv6       on tn.tid = tdv6.tid AND tdv6.vid = 6
     left join term_data tdv5  on tn.tid = tdv5.tid AND tdv5.vid = 5
     left join term_data tdv8  on tn.tid = tdv8.tid AND tdv8.vid = 8