【问题标题】:over partition by without an aggregate function, avoiding group by [closed]在没有聚合函数的情况下进行分区,避免分组 [关闭]
【发布时间】:2016-01-27 02:02:50
【问题描述】:

有什么方法可以使用像 over (partition by column) 这样的窗口函数而不将其用作聚合函数?

我有很多列,我不想使用 group by,因为我必须在 select 和 group by 中都指定。

我正在给出一个语法示例,需要以某种方式进行更正(你们会导致当我在我的实际查询中调整它时它不起作用(实际查询太长而且解释它太费时,所以只需举个例子))。

假设这是可行的:

select *,
( select
sum (column1) over (partition by column2) as sumCol1
from myTable
where column20 = column21
)
from myTable

好的,现在我想通过两个更改来做同样的事情:

1:没有聚合函数

2: column1 这次将是 DATE(据我所知,我无法将聚合函数与 date 一起使用,但就我而言尝试消除聚合,这不重要。)

我想要的应该是这样的(查询不正确,因为这是我想要实现的)

  select *,
    ( select
    column1 over (partition by column2) as Col1New
    from myTable
    where column20 = column21
    )
    from myTable

SQL Server 2012

谢谢

编辑:

样本数据:

     rN         rD          rnc      d     e   name  
    abc1m      2010-03-31   abc     5.7    2   blue   
    abc3m      2010-04-15   abc     5.7    3   blue  
    abc1y      2010-02-14   abc     5.7    4   blue   
    xfx1m      2010-02-31   xfx     1.7    2   blue  
    xfx3m      2010-03-24   xfx     1.7    1   blue  
    xfx1y      2012-03-30   xfx     1.7    1.7 red    <= d=e use this date for "red" rows
    tnt1m      2010-03-28   tnt     9.6    2   red   
    tnt3m      2010-01-12   tnt     9.6    9.6 blue   <= d=e use this date for "blue" rows
    tnt1y      2010-08-20   tnt     9.6    2   red 

预期表,请看expectedCol

rN         rD          rnc      d     e   name  expectedCol
abc1m      2010-03-31   abc     5.7    2   blue  2010-01-12 
abc3m      2010-04-15   abc     5.7    3   blue  2010-01-12 
abc1y      2010-02-14   abc     5.7    4   blue  2010-01-12 
xfx1m      2010-02-31   xfx     1.7    2   blue  2010-01-12 
xfx3m      2010-03-24   xfx     1.7    1   blue  2010-01-12 
xfx1y      2012-03-30   xfx     1.7    1.7 red   2012-03-30 
tnt1m      2010-03-28   tnt     9.6    2   red   2012-03-30 
tnt3m      2010-01-12   tnt     9.6    9.6 blue  2010-01-12 
tnt1y      2010-08-20   tnt     9.6    2   red   2012-03-30 

逻辑是这样的:当 d = e 然后查看 rD 并将该日期按名称放入 expectedCol1 组中

所以,我想写这样的东西:

select *,
(select rD over (partition by name) as expectedCol1
from myTable
where d = e)
from myTable

【问题讨论】:

  • 你能提供样本数据和期望的输出吗?这会有很大帮助。
  • 你可以随时使用聚合函数MAX()
  • 你真的需要数据样本来回答吗:is it possible to use partition by without an aggregate function?
  • 是的@CM2K,因为您的问题不清楚,并且不确定您要达到什么目的。我可以尝试猜测。但可能会浪费我的时间。
  • 看起来您最好使用 CASE 语句或子查询获取 expectedCol

标签: sql sql-server tsql sql-server-2012 window-functions


【解决方案1】:

只需为每个name 计算rD,其中d = e

WITH myDate AS ( 
      SELECT name, rD
      FROM YourTable
      WHERE d = e
)
SELECT
       t.*, m.rD as expectedCol           
FROM YourTable t
JOIN myDate m
  ON t.name = m.name

【讨论】:

  • 您的查询如何通过名称“区分”。这不是以任何方式分组
  • 我修好了。问题不清楚。
  • 经过更多测试,我发现您的解决方案是最好的。谢谢
【解决方案2】:

从您的示例数据来看,像这样更简单的东西看起来应该可以工作:

select t1.*,t2.rD as expectedCol1
from myTable t1
inner join (select name,rD from myTable where e = d) t2
on t1.name = t2.name

由于您已声明每个名称只出现一次 e=d 组合,因此 t2 子查询应该为每个名称包含一行。如果某些名称可能没有任何 e=d 的行,如果您希望将它们包含在内,您应该更改为 left join,然后考虑在这种情况下应该是什么 expectedCol1

【讨论】:

  • 您的查询似乎在选择e = d 的正确日期时起作用,但是不要知道连接中会发生什么,因为这会使myTable 从150k 行变为380 万行。有什么想法吗?
  • 我想我可以通过在 inner join (select distinct name,rD from myTable where e = d) t2 中放置一个 distinct 来解决这个问题。想法?
  • 你有我的赞成票,但我不得不将 Juan 的“已接受答案”更改为 cte 版本,因为它工作得更好更快。但是谢谢,你还是给了我一个好主意
【解决方案3】:

正如我在 cmets 中提到的,第三种方法是使用简单的子查询:

SELECT t.*, (
  SELECT rD FROM myTable t2 WHERE t2.e=t2.d AND t2.Name=t.Name
) AS ExpectedCol
FROM myTable t

【讨论】:

  • 感谢您的解决方案,但我收到错误消息:Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, &lt;, &lt;= , &gt;, &gt;= or when the subquery is used as an expression.
  • 如果你得到那个错误,那意味着你错了,当你说每个团队只有一行可以有 e=d 时。你会得到这个错误的唯一方法是如果有一个团队有不止一个这样的行。如果您更正数据,这将起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 2020-04-16
相关资源
最近更新 更多