0

我有 2 张桌子:

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 不支持它。非常感谢。

4

2 回答 2

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 上输入。请原谅拼写错误和其他语法错误...

从性能的角度来看,这可能不是很好,因为我敢打赌它需要一个临时表 + 文件排序。但是我不确定连接在这方面会表现更好,因为您需要UNION两个表中的一个......


如果由于某种原因两次检查表的成本太高并且预期结果相对较小,也许您可​​以使用临时表/视图来保存查询的中间结果(您甚至可能希望使用)。categoriesENGINE 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

于 2013-08-14T08:52:14.763 回答
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等等......

于 2013-08-14T08:38:02.033 回答