重用提取子查询的列?

时间:2013-08-14 08:29:47

标签: mysql subquery

我有两张桌子:

CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`asset_id` int(10) unsigned NOT NULL DEFAULT '0',
`title` mediumtext NOT NULL,
`published` tinyint
)

CREATE TABLE `content` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`asset_id` int(10) unsigned NOT NULL DEFAULT '0',
`title` mediumtext NOT NULL,
`catid` int(10) unsigned NOT NULL DEFAULT '0'
)
内容表中的

'catid'也存储了此内容所属的类别(即类别表中的'id') 现在,我想提取一个“有效”资产列表(包括类别和内容)。我使用以下查询,列出所有“已发布”类别及其中的内容。

SELECT asset_id, title 
FROM (SELECT asset_id, title FROM categories WHERE published=1) AS ca 
     UNION ALL 
     (SELECT asset_id, title FROM content WHERE catid IN
             (select id FROM categories WHERE published = 1)
     )

我可以得到理想的结果。但是,您可以看到,在查询中,FROM categories WHERE published = 1已经重复(在实际情况下,条件比published = 1长得多)。有没有更好的方法呢?

由于我的资产在“类别”中的“内容”中包含“图像”,因此我需要在UNION ALL的每个子查询中重复整个条件。这就像调试查询一样。

我在想是否有办法select id, asset_id, title from categories ... AS ca,然后将'id'列提取为第二个子查询FROM content WHERE id IN ca.id的集合(当然这不起作用)。我试过“WITH”但是Mysql不支持它。非常感谢你。

2 个答案:

答案 0 :(得分:1)

JOIN解决方案可能是最佳方式......

...但如果您想保留子查询语法(例如,为了便于阅读),为什么不重新组织它呢?

如果我理解得很清楚,您需要所有类别都是“已发布= 1”且所有内容属于此类别(根据asset_id)。因此,以下查询应该生成几乎相同的结果(另外一列):

SELECT asset_id, title 
FROM (SELECT asset_id, title, id FROM categories 
      UNION ALL 
      SELECT asset_id, title, catid FROM content
     ) AS s
     WHERE s.id IN (select id FROM categories WHERE published = 1)

注意我直接在SO上输入。请原谅拼写错误和其他语法错误...

从性能的角度来看,这可能不是很好,因为我敢打赌它需要一个临时表+ filesort。但是我不确定加入会在这方面表现得更好,因为你需要UNION两个表......


如果由于某种原因,如果预期结果相对较小,则检查表categories两次是非常昂贵的,也许你可以使用临时的用于保存查询的中间结果的表/视图(您甚至可能希望使用ENGINE MEMORY)。

很难说这比原始查询更高效或更高效。这取决于许多因素。无论如何,这次使用JOIN

CREATE TEMPORARY TABLE cache ENGINE MEMORY
 AS SELECT categories.asset_id as cat_aid, categories.title AS cat_t, categories.id AS cat_i,
       content.asset_id as con_aid, content.title AS con_t, content.catid AS con_i
  FROM categories
  LEFT JOIN content
  ON content.catid = categories.id
  WHERE categories.published = 1;

获得所需结果只是该表上SELECT ... UNION ...的问题:

SELECT DISTINCT cat_aid, cat_t FROM cache
UNION ALL SELECT DISTINCT con_aid, con_t FROM cache;

请参阅http://sqlfiddle.com/#!2/32ee4/2

答案 1 :(得分:0)

试试:

SELECT asset_id, title 
FROM  categories WHERE published=1
    UNION ALL 
SELECT co.asset_id, co.title FROM content co
left join categories  ca
on co.catid = ca.id 
WHERE ca.published =1;

您应该通过sqlfiddle.com提供一些简单的数据。还有一个问题,你是否有索引/ PK / FK等......