【问题标题】:How to Think in Sets如何在集合中思考
【发布时间】:2013-10-11 16:12:24
【问题描述】:

我的公司有计划、员工、客户和活动。我们要为每个程序中的每个员工审计两个随机客户端事件。

我创建了一个查询来选择过去六个月内在某个项目中发生过客户事件的所有员工。

SELECT TOP(2) 
    program_id, staff_id, client_id, event_date
FROM 
    events 
INNER JOIN 
    client ON events.client_id = client.client_id
WHERE 
    <blah, blah> --by date range, program, client showed up at event ...
ORDER BY 
    NEWID() --randomizes the top 2 picked from this set

现在,我需要针对每个程序中的每个工作人员进行迭代。员工可以在多个项目中服务,在这种情况下,我们会为每个员工/项目组合审核两个客户事件。

结果应该是这样的:

program_id  staff_id    client_id   event_date

p1  12345   abc123  8/26/2013
            xyz123  5/16/2013
p1  23456   bcd123  7/26/2013
            wxy123  4/16/2013
p2  12345   cde123  9/26/2013
            xyz123  3/16/2013
p3  34567   efg123  7/26/2013
            uvw123  5/16/2013

(将其吐出到每个程序都有单独的选项卡的 xls 会很酷。)

其他人也发布了类似的问题。我发布这个是因为它是如何在集合中思考的一个纯粹的例子。请帮助我遍历该集合。谢谢。

【问题讨论】:

  • 使用 SSMS 无关紧要。
  • @PowderSnorkel - 如果其中一个答案提供了您的解决方案,请将其标记为已回答。谢谢:)

标签: sql tsql loops foreach sql-server-2008-r2


【解决方案1】:

我有一些建议,但不是一个完整的答案。我要做的一件事是在 SQL 中按 program_id 分组,这样您就可以看到每个程序都有它的员工。

这解决了您的最后一个问题 - 可以通过自联接来平展行。

SELECT lt1.program_id  
    , lt1.staff_id    
    , lt1.client_id   
    , lt1.event_date
    , lt2.staff_id    
    , lt2.client_id   
    , lt2.event_date

FROM youLastTable lt1
    Join youLastTable on lt1.program_id = lt2.program_id

会产生这个:

p1  12345   abc123  8/26/2013   xyz123  5/16/2013
p1  23456   bcd123  7/26/2013   wxy123  4/16/2013
p2  12345   cde123  9/26/2013   xyz123  3/16/2013
p3  34567   efg123  7/26/2013   uvw123  5/16/2013

对于您的第一个问题,如何按组随机获取两行,尝试分组值并让我知道它是否有效。例如:

SELECT TOP(2) 
    program_id, staff_id, client_id, event_date
FROM 
    events 
INNER JOIN 
    client ON events.client_id = client.client_id
WHERE 
    <blah, blah> --by date range, program, client showed up at event ...
GROUP BY  program_id -- and possibly, staff_id
ORDER BY 
    NEWID() --randomizes the top 2 picked from this set

【讨论】:

  • 好的开始。现在主要的挑战是: 1. 迭代,以便我们为每个员工提供两个客户端事件。 2. 将结果输出到每个程序的单独 xls 选项卡中。谢谢!
  • 太酷了!让它工作,几乎是我需要的结果。但是,至少你让我开始思考。谢谢!现在我将尝试下面的 PARTITION BY 示例。
  • 我发现很多人很难从循环切换到集合。我经常使用临时表或简单的集合,一步一步地走,这样我就可以看到每一步的结果。这就是为什么第一个查询中的 GROUP BY program_id 将帮助您可视化和描述第二步所需的内容。话虽如此,我对随机化很模糊,但我很确定分组会有所帮助,@usr 可能有答案。
  • 好建议,谢谢。这种方法和下面的方法都很好用。工具包的新工具。不知道 ORDER BY NEWID() 是如何做到的,但是很简单地将它添加到结果集的末尾(发送到 select 语句),然后在 select 中设置一个 TOP(?)。
【解决方案2】:

我不是 100% 确定我已经理解了这些要求,但您肯定可以根据自己的需要进行调整。我将它们理解为“对于每个人员/程序组合,随机绘制两个事件”。

我会首先计算可能的人员/程序组合。然后对于每个组合我们要绘制两个随机事件:

WITH combinations AS (
 SELECT DISTINCT program_id, staff_id
 FROM events
)
SELECT e.*
FROM combinations c
CROSS APPLY (
 SELECT TOP 2 *
 FROM events e
 WHERE e.program_id = c.program_id AND e.staff_id = c.staff_id
 ORDER BY NEWID()
) e

CROSS APPLY 表示“对于每个外部行(在这种情况下从c 绘制)将以下行加入其中”。

这是一个不同的版本:

SELECT *
FROM (
 SELECT *, ROW_NUMBER() OVER (PARTITION BY program_id, staff_id ORDER BY NEWID()) r
 FROM events e
) e
WHERE e.r <= 2

更优雅。

【讨论】:

  • 现在测试,谢谢!
  • 是的!做了 PARTITION BY 然后在最后添加 ORDER BY ORDER BY program_id, program_staff
猜你喜欢
  • 2017-06-03
  • 2018-10-16
  • 2010-11-01
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
相关资源
最近更新 更多