【问题标题】:sql server - for loop - cross applysql server - for 循环 - 交叉应用
【发布时间】:2016-09-30 14:25:10
【问题描述】:

对于下表,我需要在 SQL Server 2008 中执行循环操作:

表中Day列的值可以是0到9。

For j = 0 to 9: (Iterate through the column **Day**)
   y=0;
   For k = 0 to 9:  (Iterate through the column **Day** again)
      if x[k] >= x[j]: y= y+1;

表 A:

Key|Day| x  | y |
---|---|----|---|
123| 0 |7000|   |
123| 2 |6000|   |
123| 9 |6500|   |

我使用过交叉申请并得到以下结果:

select * from TableA A
cross apply (
select Day as k, case when B.x >= A.x then 1 else 0 end as y
from TableA B 
where A.Key = B.Key
) C

输出:

Key|Day|x[j]|k |x[k]|y |y - What I need
---|---|----|--|----|--|----------------
123|0  |7000|0 |7000|1 |1 
123|0  |7000|2 |6000|0 |1 
123|0  |7000|9 |6500|0 |1 
123|2  |6000|0 |7000|1 |1 
123|2  |6000|2 |6000|1 |2 
123|2  |6000|9 |6500|1 |3 
123|9  |6500|0 |7000|1 |1 
123|9  |6500|2 |6000|0 |1 
123|9  |6500|9 |6500|1 |2 

无法弄清楚如何为每个 k 获得 y=y+1。

我不允许使用join。但是如果join的性能优于cross apply,请分享解决方案。

请帮忙。谢谢

编辑: 我尝试了以下方法来计算符合条件的运行总数:

select * from TableA A
cross apply (
select Day as k
,sum(case when B.x >= A.x then 1 else 0 end) over (partition by A.Key,A.Day) as y
from TableA B 
where A.Key = B.Key
) C

但它没有给我正确的输出。我明白了:

Key|Day|x[j]|k |x[k]|y |y - What I need
---|---|----|--|----|--|----------------
123|0  |7000|0 |7000|1 |1 
123|0  |7000|2 |6000|1 |1 
123|0  |7000|9 |6500|1 |1 
123|2  |6000|0 |7000|3 |1 
123|2  |6000|2 |6000|3 |2 
123|2  |6000|9 |6500|3 |3 
123|9  |6500|0 |7000|2 |1 
123|9  |6500|2 |6000|2 |1 
123|9  |6500|9 |6500|2 |2 

另外,当我在 over 子句中使用 order by 时,它会给我一个错误:

The Parallel Data Warehouse (PDW) features are not enabled.

【问题讨论】:

  • 为什么“不允许”使用joincross apply 也是一个“连接”——横向交叉连接。
  • 遗憾的是,我对此没有明确的答案。数据库每分钟处理大量事务。但是我必须执行上述操作的表每天只更新一次,所以如果使用 join 的解决方案性能更好,我会尝试说服我的“上级”。
  • 您在交叉连接方面做得对,但您遇到了总计(最后一列)。尝试搜索它。
  • 您需要一个运行总计(有条件)。 SQL Server 2012+ 可以有效地做到这一点。在 2008 年,使用游标可能更有效。或者在客户端计算运行总和。
  • 您的最新查询确实给出了正确的最后一列。你还想要什么?

标签: sql sql-server sql-server-2008


【解决方案1】:

你很亲密。我正在运行 SQL Server 2016。结果应该是一样的。注意您预期结果中的 Key 和 Day 列与 TableA 中的原始数据不匹配。

WITH TableY AS
(
    SELECT A.[Key], A.[Day], A.X AS xj, B.[Day] AS k, B.X AS xk, 
    (CASE WHEN B.X >= A.X THEN 1 ELSE 0 END) AS y
    FROM @TableA AS A
    INNER JOIN @TableA AS B ON A.[Key] = B.[Key]
)
SELECT *,
    SUM(y) OVER(
         PARTITION BY [Key], [Day] 
         ORDER BY k 
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS 'RunningTotalY'
FROM TableY
ORDER BY [Key], [Day], xj, k;

不确定 PDW 错误是如何产生的。

【讨论】:

  • 谢谢,我更正了 TableA 数据,使结果和数据匹配。但此代码在 SQL Server 2008 中不起作用。适用于 SQL Server 2012 及更高版本。所以我必须使用@Vladimir 提到的游标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
相关资源
最近更新 更多