如何在子查询中使用 select 中的值?

Posted

技术标签:

【中文标题】如何在子查询中使用 select 中的值?【英文标题】:How to use value from select in a subquery? 【发布时间】:2013-11-14 09:35:44 【问题描述】:

我正在尝试加入一个选择语句。但是子查询选择返回的行太多,使其非常慢 - 因为我无法从第一个选择中获取 ID 到子查询中。

错误是:

错误代码:1054。“where 子句”中的未知列“ritzau_data.News.id”

如何在第一个选择中获取此 id 到连接内的选择中? 我在 MSSQL 中做了类似的事情——效果很好。我还将粘贴有效的 MSSQL 代码。

mysqlCode(不工作):

select News.id as newsid, header as title, content as contents, created as published_time, 2883 as drupalid, isins, categories, NewsTypes.npName from ritzau_data.News,
(
    select idNews, group_concat(isin separator ', ') as isins
    from ritzau_data.NewsIsin
    where idNews = ritzau_data.News.id
    group by idNews

) as isins,
(
    select idNews, group_concat(distinct Category separator ', ') as categories
    from ritzau_data.NewsTags

    inner join ritzau_data.TagsCategoriesMap on NewsTags.idTag = TagsCategoriesMap.idTags
    inner join ritzau_data.Categories on TagsCategoriesMap.idCategories = Categories.id
    where idNews = ritzau_data.News.id
    group by idNews
) as categories

left join ritzau_data.NewsTypes on News.idType = NewsTypes.id
inner join ritzau_data.NewsReceivers on News.id = NewsReceivers.idNews
where ritzau_data.News.id > 100 and idReceiver = 3
order by News.id
limit 100;

MSSQLCode(工作):

SELECT TOP 1000 news.id AS newsid, 
        cast(title as varchar(256)) AS title, cast(contents as text)AS contents, published_time, users.drupalid,
        cast (STUFF(
            (
                SELECT ',' + isin
                FROM news_instruments t1
                left join instruments t2 on t1.instrument_id = t2.id
                where news_id = news.id
                FOR XML PATH('')
            ),1,1,''
        ) as text) AS isins,
        cast(STUFF(
            (
                SELECT ',' + t2.name
                FROM news_categories t1
                left join categories t2 on t1.category_id = t2.id
                where news_id = news.id
                FOR XML PATH('')
            ),1,1,''
        ) as text) AS categories
        from news
        left join users on news.locked_userid = users.id
        where news.id > @offsetid

第一个查询 - 它工作但非常慢

select News.id as newsid, header as title, content as contents, created as published_time, 2883 as drupalid, isins, categories, NewsTypes.npName from ritzau_data.News    
left join ritzau_data.NewsTypes on News.idType = NewsTypes.id
inner join ritzau_data.NewsReceivers on News.id = NewsReceivers.idNews
select idNews, group_concat(isin separator ', ') as isins
        from ritzau_data.NewsIsin
        where idNews = News.id
        group by idNews
) as isins on News.id = isins.idNews
left join (
        select idNews, group_concat(distinct Category separator ', ') as categories
        from ritzau_data.NewsTags

        inner join ritzau_data.TagsCategoriesMap on NewsTags.idTag = TagsCategoriesMap.idTags
        inner join ritzau_data.Categories on TagsCategoriesMap.idCategories = Categories.id
        where idNews = News.id
        group by idNews
) as categories on News.id = categories.idNews
where News.id > @idoffset and idReceiver = 3
order by News.id
limit 100;

【问题讨论】:

我做了这 2 个程序 - 一个用于提取 id,一个用于提取数据。现在速度更快了。 【参考方案1】:

问题是,新闻表在不同的模式中,因此您必须在 where 子句中提供完全限定名称:

select [...]
from ritzau_data.News
[...]
where ritzau_data.News.id > @idoffset and idReceiver = 3
order by News.id
limit 100;

优雅的方式是给表格起别名:

select [...]
from ritzau_data.News nw
[...]
where nw.id > @idoffset and idReceiver = 3
order by nw.id
limit 100;

更新: 您必须将子查询中的联接从子查询中拉到新闻表中:

SELECT News.id AS newsid, header AS title, content AS contents, created AS published_time, 2883 AS drupalid, isins, categories, NewsTypes.npName 
FROM ritzau_data.News ritzau_data.News
JOIN
(
    SELECT idNews, GROUP_CONCAT(isin SEPARATOR ', ') AS isins
    FROM ritzau_data.NewsIsin
    GROUP BY idNews

) AS isins
  ON isins.idNews = ritzau_data.News.id
 JOIN
(
    SELECT idNews, GROUP_CONCAT(DISTINCT Category SEPARATOR ', ') AS categories
    FROM ritzau_data.NewsTags

    INNER JOIN ritzau_data.TagsCategoriesMap ON NewsTags.idTag = TagsCategoriesMap.idTags
    INNER JOIN ritzau_data.Categories ON TagsCategoriesMap.idCategories = Categories.id
    GROUP BY idNews
) AS categories
  ON categories.idNews = ritzau_data.News.id
LEFT JOIN ritzau_data.NewsTypes ON News.idType = NewsTypes.id
INNER JOIN ritzau_data.NewsReceivers ON News.id = NewsReceivers.idNews
WHERE ritzau_data.News.id > 100 AND idReceiver = 3
ORDER BY News.id
LIMIT 100;

更新 2: 将与 News 的连接拉入子查询:

SELECT News.id AS newsid, header AS title, content AS contents, created AS published_time, 2883 AS drupalid, isins, categories, NewsTypes.npName 
FROM ritzau_data.News ritzau_data.News
JOIN
(
    SELECT idNews, GROUP_CONCAT(isin SEPARATOR ', ') AS isins
    FROM ritzau_data.NewsIsin
    JOIN ritzau_data.News ON idNews = ritzau_data.News.id
    GROUP BY idNews

) AS isins
 JOIN
(
    SELECT idNews, GROUP_CONCAT(DISTINCT Category SEPARATOR ', ') AS categories
    FROM ritzau_data.NewsTags

    INNER JOIN ritzau_data.TagsCategoriesMap ON NewsTags.idTag = TagsCategoriesMap.idTags
    INNER JOIN ritzau_data.Categories ON TagsCategoriesMap.idCategories = Categories.id
    JOIN ritzau_data.News ON idNews = ritzau_data.News.id
    GROUP BY idNews
) AS categories
LEFT JOIN ritzau_data.NewsTypes ON News.idType = NewsTypes.id
INNER JOIN ritzau_data.NewsReceivers ON News.id = NewsReceivers.idNews
WHERE ritzau_data.News.id > 100 AND idReceiver = 3
ORDER BY News.id
LIMIT 100;

【讨论】:

添加全名没有任何作用。我已经用新代码更新了问题。 我现在看到了问题,您在类别子选择中使用了News.id。这不起作用,您必须从类别中选择所有行,然后将该子查询与 News 表连接起来,或者您必须在子查询中添加新闻表。我会更新我的答案。 这确实有效 - 它看起来很像我所做的第一个查询(请参阅更新的问题),但运行查询需要 122 秒,因为连接返回的行太多。联接应该只获得在开头选择了 News.is 的结果。 您可以随时将新闻表添加到子查询中。如果索引设置正确,可能会更快,请参阅更新的解决方案。 嗯,没有更快。我仍然认为这是加入太多数据。

以上是关于如何在子查询中使用 select 中的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在子查询中使用外部查询中的列从另一个表中获取结果?

MySQL在SELECT子句中关联子查询

如何在子查询的 WHERE 子句中使用来自 UNNEST 的多个值?

在 T-SQL 中,如何在子查询中引用表变量?

如何在子查询中使用主查询中的列?

在子查询中使用多个表