Sql 如何使用group by仅选择一列?

Sql 如何使用group by仅选择一列?,sql,sql-server-2008,crud,Sql,Sql Server 2008,Crud,我试图从每个门户中只选择一行,最后一行是按日期选择的,但我在使用group by/distinct时遇到了问题 使用这段代码,我只能选择我需要的portalId,但没有任何数据 Select relNews.PortalId from news left join relNews on relNews.NewsId= news.NewsId group by relNews.PortalId 当我在代码中添加一个或多个数据列时,select会显示所有信息,而不仅仅是每个门户的一个信息 Sele

我试图从每个门户中只选择一行,最后一行是按日期选择的,但我在使用group by/distinct时遇到了问题

使用这段代码,我只能选择我需要的portalId,但没有任何数据

Select relNews.PortalId
from news
left join relNews on relNews.NewsId= news.NewsId
group by relNews.PortalId
当我在代码中添加一个或多个数据列时,select会显示所有信息,而不仅仅是每个门户的一个信息

Select relNews.PortalId, news.NewsId
from news
left join relNews on relNews.NewsId= news.NewsId
group by relNews.PortalId, news.NewsId
我知道这是我在这里错过的一个小把戏,但我只是不记得是什么

使现代化 让我们为这个例子创建虚拟表。这些表格是新闻和新闻,我在这里尽量简短

表格新闻

新闻ID 标题 描述 日期 表relNews

雷纽西德 新闻ID 便携式 注:

relNews可以有N个相同NewsId的寄存器 我需要根据news.Date为每个portalId选择最后一个寄存器。 让我们说:

表格新闻

NewsId==1 标题==“测试” Description==“测试” 日期==“2013-01-01 00:00:00”

NewsId==2

Title==“test2” Description==“test2” 日期==“2013-01-01 03:00:00”

NewsId==3

Title==“test3” Description==“test3” 日期==“2013-01-02 00:00:00” 表relNews

RelNewsId==1 NewsId==1 PortalId==1

RelNewsId==2

NewsId==1 PortalId==2

RelNewsId==3

NewsId==2 PortalId==1

RelNewsId==4

NewsId==3 PortalId==3 这些数据应带来:

RelNewsId==2;RelNewsId==3;RelNewsId==4

我可以通过以下代码获得我想要的结果:

Select top 1 relNews.PortalId, news.NewsId, news.date
from news
left join relNews on relNews.NewsId= news.NewsId
where relNews.PortalId == 1
group by relNews.PortalId, news.NewsId
order by news.date desc
UNION
Select top 1 relNews.PortalId, news.NewsId, news.date
from news
left join relNews on relNews.NewsId= news.NewsId
where relNews.PortalId == 2
group by relNews.PortalId, news.NewsId
order by news.date desc
UNION
Select top 1 relNews.PortalId, news.NewsId, news.date
from news
left join relNews on relNews.NewsId= news.NewsId
where relNews.PortalId == 3
group by relNews.PortalId, news.NewsId
order by news.date desc

然后我得到所有3个结果。

假设按顺序创建了一个newsid,并且新闻是一个项目,那么以下可能是您想要的:

Select relNews.PortalId, max(relnews.newsid) as MostRecentNews
from relNews
group by relNews.PortalId

如果您只需要id,则不需要加入。假定按顺序创建了newsid,并且新闻是一个项目,那么您可能需要以下内容:

Select relNews.PortalId, max(relnews.newsid) as MostRecentNews
from relNews
group by relNews.PortalId

如果您只需要id,则不需要加入。

您将按日期对门户id进行排名

 select relNews.PortalId
 from news
 left join relNews on relNews.newsId = news.Id
 -- select rows for which there is no greater date than this row's date
 left outer join relNews2 on relNews.newsId = relNews2.newsId and relNews.date < relNews2.date
 where relNews2.PortalId is null
 group by relNews.PortalId, relNews.newsId

您将按日期对门户id进行排名

 select relNews.PortalId
 from news
 left join relNews on relNews.newsId = news.Id
 -- select rows for which there is no greater date than this row's date
 left outer join relNews2 on relNews.newsId = relNews2.newsId and relNews.date < relNews2.date
 where relNews2.PortalId is null
 group by relNews.PortalId, relNews.newsId

当一个新闻行可能有多个新闻行时,您必须提供某种方式来指示您想要哪一个新闻行。正如您所发现的,当您按一个列进行分组(该列可以为每个父级包含多个值)时,就会得到多行。有几种方法可以做到这一点。因为您使用的是SQL Server 2008,所以有几个选项

交叉/外部应用-如果要在没有匹配的新闻行时排除新闻行,请将外部应用更改为交叉应用

行号

聚合-这比它看起来需要的复杂得多,但我假设newsDate不是每个newsID唯一的。如果它是唯一的,那么它就更简单。此版本适用于SQL 2000。这可能也是我提供的所有选项中性能最差的查询。请注意,UniqueColumn是保证每个newsID具有唯一值的任何列,可用于在newsDate的关系中进行选择

如果每个news.Id的newsDate确实是唯一的,那么以下是该查询:

SELECT
   R.Whatever,
   N.Whatever
FROM
   dbo.RelNews R
   LEFT JOIN (
      dbo.News N
      INNER JOIN (
         SELECT N.Id, MaxDate = Max(N.newsDate)
         FROM dbo.News N
         GROUP BY N.Id
      ) X ON N.Id = X.Id
      AND N.newsDate = X.MaxDate
   ) ON R.newsId = N.Id
子查询—一次只能提取一列,但在SQL 2000中可以正常工作,并且使用适当的索引应该可以很好地执行。对于多个列,它可能会执行糟糕的操作,因为它可能会对每个列执行单独的查询

SELECT
   R.Whatever,
   NWhatever = (
      SELECT TOP 1 N.Whatever
      FROM dbo.News N
      WHERE R.newsId = N.Id
      ORDER BY N.newsDate DESC
   )
FROM
   dbo.relNews R
ON子句中的子查询—如果要提取多个列,可能是SQL 2000的最佳查询。必须在新闻表中点击两次,但如果有适当的索引,情况应该不会那么糟糕。请注意,UniqueColumn是保证每个newsID具有唯一值的任何列,可用于在newsDate的关系中进行选择

Logical Last—SQL 2000的另一个可能的优秀执行者。这是与相同的逻辑查询,但表达方式略有不同

SELECT
   R.Whatever,
   N.Whatever
FROM
   dbo.relNews R
   LEFT JOIN dbo.News N
      ON R.newsId = N.Id
      AND NOT EXISTS (
         SELECT *
         FROM dbo.News X
         WHERE
            N.Id = X.Id
            AND (
               N.newsDate < X.newsDate
               OR (
                  N.newsDate = X.newsDate
                  AND N.UniqueColumn < X.UniqueColumn
               )
            )
      )
在您使用的数据库版本中,选项1可能最适合您


最后一点注意:一如既往,需要进行测试。所有这些不同查询的性能将取决于许多因素:数据的模式每个新闻项的日期有多少,确切的索引,表的宽度,以及是否添加额外的条件,例如,如果外部relNews表上的条件只返回几行,那么我建议的第1行将不会很好。如果您发现一个查询没有提供令人满意的执行时间,请尝试另一个查询。

当一个新闻行可能有多个查询时,您必须提供某种方式来指示所需的新闻行。正如您所发现的,当您按一个列进行分组(该列可以为每个父级包含多个值)时,就会得到多行。有几种方法可以做到这一点。因为您使用的是SQL Server 2008,所以有几个选项

交叉/外部应用-如果要在没有匹配的新闻行时排除新闻行,请将外部应用更改为交叉应用

行号

聚合-这比它看起来需要的复杂得多,但我假设newsDate不是每个newsID唯一的。如果它是唯一的,那么它就更简单。此版本适用于SQL 2000。这可能也是表现最差的一次 查询我提供的所有选项。请注意,UniqueColumn是保证每个newsID具有唯一值的任何列,可用于在newsDate的关系中进行选择

如果每个news.Id的newsDate确实是唯一的,那么以下是该查询:

SELECT
   R.Whatever,
   N.Whatever
FROM
   dbo.RelNews R
   LEFT JOIN (
      dbo.News N
      INNER JOIN (
         SELECT N.Id, MaxDate = Max(N.newsDate)
         FROM dbo.News N
         GROUP BY N.Id
      ) X ON N.Id = X.Id
      AND N.newsDate = X.MaxDate
   ) ON R.newsId = N.Id
子查询—一次只能提取一列,但在SQL 2000中可以正常工作,并且使用适当的索引应该可以很好地执行。对于多个列,它可能会执行糟糕的操作,因为它可能会对每个列执行单独的查询

SELECT
   R.Whatever,
   NWhatever = (
      SELECT TOP 1 N.Whatever
      FROM dbo.News N
      WHERE R.newsId = N.Id
      ORDER BY N.newsDate DESC
   )
FROM
   dbo.relNews R
ON子句中的子查询—如果要提取多个列,可能是SQL 2000的最佳查询。必须在新闻表中点击两次,但如果有适当的索引,情况应该不会那么糟糕。请注意,UniqueColumn是保证每个newsID具有唯一值的任何列,可用于在newsDate的关系中进行选择

Logical Last—SQL 2000的另一个可能的优秀执行者。这是与相同的逻辑查询,但表达方式略有不同

SELECT
   R.Whatever,
   N.Whatever
FROM
   dbo.relNews R
   LEFT JOIN dbo.News N
      ON R.newsId = N.Id
      AND NOT EXISTS (
         SELECT *
         FROM dbo.News X
         WHERE
            N.Id = X.Id
            AND (
               N.newsDate < X.newsDate
               OR (
                  N.newsDate = X.newsDate
                  AND N.UniqueColumn < X.UniqueColumn
               )
            )
      )
在您使用的数据库版本中,选项1可能最适合您


最后一点注意:一如既往,需要进行测试。所有这些不同查询的性能将取决于许多因素:数据的模式每个新闻项的日期有多少,确切的索引,表的宽度,以及是否添加额外的条件,例如,如果外部relNews表上的条件只返回几行,那么我建议的第1行将不会很好。如果您发现一个查询没有提供令人满意的执行时间,请尝试另一个查询。

最简单、最短、性能最高的方法也是通过使用行数过度分配。。。详情如下:

SELECT TOP 20 News.*, 
ROW_NUMBER() Over(Partition by relNews.PortalId Order By news.Id DESC ) R
FROM news LEFT JOIN relNews on relNews.newsId = news.Id
ORDER BY R
我在这里使用前20名,因为这些是显示每个门户中第一条新闻的门户计数


这是最好的例子来展示和表达分区的用法,也是最简单、最短、性能最高的方法是使用行数过分区。。。详情如下:

SELECT TOP 20 News.*, 
ROW_NUMBER() Over(Partition by relNews.PortalId Order By news.Id DESC ) R
FROM news LEFT JOIN relNews on relNews.newsId = news.Id
ORDER BY R
我在这里使用前20名,因为这些是显示每个门户中第一条新闻的门户计数



这是通过

显示和表达分区用法的最佳示例。选择带来所有信息是什么意思?请选择什么DBMS和版本?MS SQL Server 2008?MySQL?甲骨文?对不起,我没有解释。假设只有一列,我选择了6行,但是如果我添加ID列,我选择了10行,例如什么是项目?您的表名为news和relNews。@ErikE SQL Server 2008将把它放在一个问题中对不起,习惯于Arqade,标记越少越好。您所说的选择带来了所有信息是什么意思?请问是什么DBMS和版本?MS SQL Server 2008?MySQL?甲骨文?对不起,我没有解释。假设只有一列,我选择了6行,但是如果我添加ID列,我选择了10行,例如什么是项目?您的表名为news和relNews。@ErikE SQL Server 2008将把它放在一个问题中,抱歉,习惯于Arqade,在Arqade中,Tag越少越好。我认为依赖按顺序创建newsid是不明智的。有时数据输入较晚,或通过后端输入,或事后更正。依赖身份值将插入顺序与业务含义顺序等同起来的系统是脆弱的,我从经验中得出结论。+1很好,但在我的情况下,我需要的不仅仅是ID。我只使用问题中的ID使其变小@ErikE在数据更新点上是正确的,例如,因为日期不是创作日期,而是展览日期,所以在你的作品中你错过了内在的加入新闻query@AtheerMostafa . . . 不,我不小心在on子句中留下了。@ErikE。这就是为什么我在回答这个问题之前要明确地说出我的假设。我认为依靠按顺序创建newsid是不明智的。有时数据输入较晚,或通过后端输入,或事后更正。依赖身份值将插入顺序与业务含义顺序等同起来的系统是脆弱的,我从经验中得出结论。+1很好,但在我的情况下,我需要的不仅仅是ID。我只使用问题中的ID使其变小@ErikE在数据更新点上是正确的,例如,因为日期不是创作日期,而是展览日期,所以在你的作品中你错过了内在的加入新闻query@AtheerMostafa . . . 不,我不小心在on子句中留下了。@ErikE。这就是为什么我在回答问题之前明确地说出我的假设。无效的列名“newsDate”。当我测试select注释时,我更改为正确的列名。您使用的是我列表中的哪个查询?还有,也许我是在理解你的表结构,还是什么?请提供newsDate列和UniqueColumn的名称,并指出它们位于哪个表中。如果我的查询对你不起作用,那是因为我不太了解你的结构,需要更多的信息。相信我:当你提供足够的信息,我们将能够提供
第三个很抱歉,忘了提一下,我刚才在那个查询中发现了一个错误。请再检查一下。然而,这可能是我提供的性能最差的查询。你能用另一个吗?注意:我犯了一个很大的错误。1不知何故我完全忽略了PortalId,2我假设relNews表每个newsId只有一行,而news表每个Id有许多行。我现在明白了,我可能完全错了。请您更新您的问题,更详细地介绍您的表及其结构,并提供一些示例行,以便我可以修复所有查询以正常工作?列名“newsDate”无效。当我测试select注释时,我更改为正确的列名。您使用的是我列表中的哪个查询?还有,也许我是在理解你的表结构,还是什么?请提供newsDate列和UniqueColumn的名称,并指出它们位于哪个表中。如果我的查询对你不起作用,那是因为我不太了解你的结构,需要更多的信息。相信我:当你提供足够的信息时,我们将能够给出正确的查询。第三个很抱歉,忘了提及我刚才在查询中发现了一个错误。请再检查一下。然而,这可能是我提供的性能最差的查询。你能用另一个吗?注意:我犯了一个很大的错误。1不知何故我完全忽略了PortalId,2我假设relNews表每个newsId只有一行,而news表每个Id有许多行。我现在明白了,我可能完全错了。请您更新您的问题,提供关于您的表及其结构的更多详细信息,并提供一些示例行,以便我可以修复所有查询,使其正常工作。编写的此查询不起作用,因为relNews2的联接没有在Id上联接,因此整个表中仅显示新闻表中最近的一行。另外,请注意,您的查询依赖于新闻表中每个news.Id的日期是不同的,这不是一个安全的假设。啊,感谢您捕获了这两个错误。我对连接条件进行了编辑,以包含newsId。关于日期的唯一性,你是绝对正确的。我假设了不同的日期,因为问题说最后一个是日期。我的意思是。。。没有relNews2表。。。o、 OThis编写的查询将不起作用,因为relNews2的连接不是在Id上连接的,因此将只显示整个表中新闻表中最近的一行。另外,请注意,您的查询依赖于新闻表中每个news.Id的日期是不同的,这不是一个安全的假设。啊,感谢您捕获了这两个错误。我对连接条件进行了编辑,以包含newsId。关于日期的唯一性,你是绝对正确的。我假设了不同的日期,因为问题说最后一个是日期。我的意思是。。。没有relNews2表。。。o、 谢谢你的回答。但这不是我需要的。我更新了我的问题,试图把它弄清楚。谢谢你的回答。但这不是我需要的。我更新了我的问题,试图把它弄清楚。