Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL Server 2012中使用Top_Sql_Sql Server - Fatal编程技术网

在SQL Server 2012中使用Top

在SQL Server 2012中使用Top,sql,sql-server,Sql,Sql Server,我有一个表联系人,父表到表活动。我想为每个联系人选择最新的活动,但要获得多行 这是我的疑问: select top 30 * from Contacts o, Activity d where o.ID = d.contact and d.ID > 401061 and Last_Action is null order by d.activity_date desc 我想我需要上衣?但不确定如何在这里实施。

我有一个表联系人,父表到表活动。我想为每个联系人选择最新的活动,但要获得多行

这是我的疑问:

select top 30 
     * 
from 
     Contacts o, Activity d  
where 
     o.ID = d.contact 
     and d.ID > 401061 
     and Last_Action is null 
order by 
     d.activity_date desc

我想我需要上衣?但不确定如何在这里实施。任何帮助都将不胜感激。

这只是一个小小的猜测,因为我看不出您的表在列方面是什么样子的,但也许这个或类似的东西会起作用

select top 30 * from Contacts o, 
(SELECT contact, max(activity_date) FROM Activity GROUP BY contact) d  
    where o.ID = d.contact And d.ID > 401061 
    and Last_Action is null order by d.activity_date desc
这里有一种使用notexists的方法,可以在大多数dbs上使用。您基本上是在每个联系人中选择每个活动,其中不存在更新的活动,因此它是最新的活动

select top 30 * from activity a
join contact c on c.id = a.contact
where not exists (
    select 1 from activity b
    where b.contact = a.contact
    and b.activity_date > a.activity_date
) and last_action is null and a.id > 401061
order by a.activity_date desc
您可以使用row_number为每个联系人的活动编号。在外部查询中,您可以只筛选每个联系人的最新活动:

select  top 30 * 
from    (
        select  row_number() over (
                    partition by o.ID
                    order by d.activity_date desc) as rn
        ,       *
        from    Contacts o
        join    Activity d
        on      o.ID = d.contact 
        where   d.ID > 401061 
                and Last_Action is null 
        ) as SubQueryAlias
where   rn = 1 -- Only last activity per contact
order by 
         activity_date desc

我想您应该使用子查询:

SELECT TOP 30 *
FROM
  Contacts AS o,
  ( SELECT
      contact,
      MAX( activity_date ) AS activity_date
    FROM
      Activity
    WHERE
      contact > 401061 AND
      Last_Action IS NULL
    GROUP BY
      contact
  ) AS d
WHERE
  o.ID = d.contact
ORDER BY
  d.activity_date

假设您希望每个联系人执行前30个操作,这正是CROSS APPLY发明的目的

类似于以下的情况-不确定性是因为我看不到您的数据示例

select
    *
from
    contacts
    cross apply (
        select top 30
            *
        from
            activity
        where
                contacts.id = activity.contact
                and 401061 < activity.id
    ) as _ca
where
    last_action is null -- Perhaps you could move this into the CA - but we don't know which table it's from
order by
    activity.activity_date desc;
编辑 使用cte

WITH cte AS 
(
    SELECT *, 
           ROW_NUMBER() OVER (PARTITION BY contact ORDER BY activity_date DESC) rn
    FROM   Activity
    WHERE  d.ID > 401061  AND Last_Action IS NULL 
)
SELECT TOP 30 * 
FROM Contacts o 
     JOIN cte d  ON o.Id = d.contact 
WHERE d.rn = 1
ORDER BY cte.activity_date DESC

如果我想要30个联系人,每个联系人都有最新的活动呢?啊……我知道了。抱歉-我认为这是一个太简单的修复。Eep在1980年的连接语法。。。为什么不使用SQL-92的内部联接。。。开?我试着让它与OPs原始查询类似你是说你想要每个联系人的最新活动20多年前,在ANSI-92 SQL标准中,旧样式的逗号分隔表列表样式被正确的ANSI联接语法所取代,不鼓励使用它。你是说b.activity\u date>a.activity\u date而不是b.id>a.id?您需要一个ORDERBY子句,前30名才能正常工作。这将查找每个用户最近的30项活动。OP正在查找30个最近活动的用户。我想为联系人选择最新的活动。我想我这样解释是可以原谅的。编辑:好的,我现在看到了下面的更新aa并相应地添加了新建议。编辑后的版本应能正常工作。但是交叉应用将强制对contacts中的每一行执行子查询,因此我希望此处的其他查询速度更快。我倾向于使用此方法,因为我通常会查找超过1个最大值,而max当然无法处理。是的,也许在单一情况下,这是效率较低的。查询优化者在这里能不能做点聪明的事然而,我认为这取决于数据和执行环境——因为在一种情况下,您需要遍历所有编号的行,然后过滤它们;在另一种情况下,您可以按行查询,但会随行过滤。永远不知道查询优化器:但如果它会重写这一点,我会感到惊讶。交叉应用通常意味着程序员需要一个相关的子查询,这实际上并不比OP使用的where连接好多少。它对OP来说是有意义的,所以这就是我离开它的原因。快速指出标准已经发展,并且有更好的方法来实现相同的结果,对OP会更有帮助。@下划线\u定义得更好。。你是说视觉上?尽管我个人使用JOIN,但这似乎是我个人的偏好。
WITH cte AS 
(
    SELECT *, 
           ROW_NUMBER() OVER (PARTITION BY contact ORDER BY activity_date DESC) rn
    FROM   Activity
    WHERE  d.ID > 401061  AND Last_Action IS NULL 
)
SELECT TOP 30 * 
FROM Contacts o 
     JOIN cte d  ON o.Id = d.contact 
WHERE d.rn = 1
ORDER BY cte.activity_date DESC