我有两张桌子:
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不支持它。非常感谢你。
答案 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;
答案 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等......