1

可能重复:
如何使用两个内部联接修改此查询,以使其停止给出重复的结果?

我无法让我的查询正常工作。

SELECT itpitems.identifier, itpitems.name, itpitems.subtitle, itpitems.description, itpitems.itemimg, itpitems.mainprice, itpitems.upc, itpitems.isbn, itpitems.weight, itpitems.pages, itpitems.publisher, itpitems.medium_abbr, itpitems.medium_desc, itpitems.series_abbr, itpitems.series_desc, itpitems.voicing_desc, itpitems.pianolevel_desc, itpitems.bandgrade_desc, itpitems.category_code, itprank.overall_ranking, itpitnam.name AS artist, itpitnam.type_code FROM itpitems 
        INNER JOIN  itprank ON (itprank.item_number = itpitems.identifier) 
        INNER JOIN  (SELECT DISTINCT type_code FROM itpitnam) itpitnam ON (itprank.item_number = itpitnam.item_number)   
        WHERE mainprice > 1    
        LIMIT 3

我在“字段列表”中不断收到未知列“itpitnam.name”。

但是,如果我将 DISTINCT type_code 更改为 *,我不会收到该错误,但我也不会得到我想要的结果。

这是一个很大的结果表,所以我正在制作一个虚拟示例......

使用 *,我得到类似:

+-----------+---------+----------+
| identifier| name    | type_code|
+-----------+---------+----------+
| 2         | Joe     | A        |
| 2         | Amy     | R        |
| 7         | Mike    | B        |
+-----------+------------+-------+

这里的问题是我有两个 identifier = 2 实例,因为 type_code 不同。 在查询的外部尝试了 GROUP BY,但是它筛选了这么多记录,这给服务器造成了太大的压力,所以我试图找到一种替代方法来获得我需要的结果。

我想要实现的(使用相同的虚拟输出)看起来像这样:

+-----------+---------+----------+
| identifier| name    | type_code|
+-----------+---------+----------+
| 2         | Joe     | A        |
| 7         | Mike    | B        |
| 8         | Sam     | R        |
+-----------+------------+-------+

无论 type_code 是否不同,它都应该跳过重复的标识符。

有人可以帮我修改此查询以获得上图中模拟的结果吗?

4

2 回答 2

1

一种方法是使用内联视图,就像您已经拥有的查询一样。但是,您可以使用 GROUP BY 来消除重复项,而不是使用 DISTINCT。满足您要求的最简单的内联视图是:

( SELECT n.item_number, n.name, n.type_code
    FROM itpitnam n
   GROUP BY n.item_number
) itpitnam

虽然它不确定从 itpitnam 的哪一行检索 name 和 type_code 的值。更精细的内联视图可以使其更具体。


解决此类问题的另一种常见方法是在 SELECT 列表中使用相关子查询。对于返回一小组行,这可以执行得相当好。但是对于返回大集合,有更有效的方法。

SELECT i.identifier
     , i.name
     , i.subtitle
     , i.description
     , i.itemimg 
     , i.mainprice
     , i.upc
     , i.isbn
     , i.weight
     , i.pages
     , i.publisher
     , i.medium_abbr
     , i.medium_desc
     , i.series_abbr
     , i.series_desc
     , i.voicing_desc
     , i.pianolevel_desc
     , i.bandgrade_desc
     , i.category_code
     , r.overall_ranking
     , ( SELECT n1.name
           FROM itpitnam n1
          WHERE n1.item_number = r.item_number
          ORDER BY n1.type_code, n1.name
          LIMIT 1
       ) AS artist
     , ( SELECT n2.type_code
           FROM itpitnam n2
          WHERE n2.item_number = r.item_number
          ORDER BY n2.type_code, n2.name
          LIMIT 1
       ) AS type_code
  FROM itpitems i
  JOIN itprank r
    ON r.item_number = i.identifier
 WHERE mainprice > 1
 LIMIT 3

该查询将返回指定的结果集,但有一个显着差异。原始查询显示itpitnam表的 INNER JOIN。这意味着只有在表中有匹配行时才会返回一行itpitnam。然而,上面的查询模拟了一个 OUTER JOIN,当在itpitnam.


更新

为了获得这些相关子查询的最佳性能,您需要一个适当的可用索引,

... ON itpitnam (item_number, type_code, name)

该索引是最合适的,因为它是“覆盖索引”,可以完全从索引中满足查询,而无需引用基础表中的数据页,并且在前导列上有相等谓词,在接下来的两列上有 ORDER BY,这样可以避免“排序”操作。

--

如果您保证 itpitnam 表中的type_codeorname列不是 NULL,则可以添加谓词来消除“缺少”匹配行的行,例如

HAVING artist IS NOT NULL

(添加它可能会对性能产生影响。)如果没有这种保证,您需要添加一个 INNER JOIN 或一个测试匹配行是否存在的谓词,以获得 INNER JOIN 行为。


于 2013-02-02T05:11:23.613 回答
0
SELECT  a.*
        b.overall_ranking, 
        c.name AS artist, 
        c.type_code 
FROM    itpitems a
        INNER JOIN  itprank b 
            ON b.item_number = a.identifier
        INNER JOIN  itpitnam c
            ON b.item_number = c.item_number
        INNER JOIN
        (
            SELECT  item_number, MAX(type_code) code
            FROM    itpitnam
            GROUP   BY item_number
        ) d ON  c.item_number = d.item_number AND
                c.type_code = d.code

WHERE   mainprice > 1    
LIMIT   3

后续问题:您能否发布表模式以及表之间的关系?所以我会知道要链接的列是什么。

于 2013-02-02T04:53:07.617 回答