Sql 使用UNPIVOT从转换为列数据的行数据中选择MAX()值,然后选择MAX()

Sql 使用UNPIVOT从转换为列数据的行数据中选择MAX()值,然后选择MAX(),sql,sql-server,pivot,max,Sql,Sql Server,Pivot,Max,我有一个名为amounts的表,如下所示: // structure 1 +-----+-----+-----+-----+-----+-----+-----+ | MON | TUE | WED | THU | FRI | SAT | SUN | +-----+-----+-----+-----+-----+-----+-----+ | 1 | 6 | 3 | 1 | 1 | 3 | 0 | +-----+-----+-----+-----+-----+-----+

我有一个名为amounts的表,如下所示:

// structure 1
+-----+-----+-----+-----+-----+-----+-----+
| MON | TUE | WED | THU | FRI | SAT | SUN |
+-----+-----+-----+-----+-----+-----+-----+
| 1   | 6   | 3   | 1   | 1   | 3   | 0   |
+-----+-----+-----+-----+-----+-----+-----+
// structure 2
+-----+-----+
| DAY | AMT |
+-----+-----+
| MON | 1   |
+-----+-----+
| TUE | 6   |
+-----+-----+
| WED | 3   |
+-----+-----+
| THU | 1   |
+-----+-----+
| FRI | 1   |
+-----+-----+
| SAT | 3   |
+-----+-----+
| SUN | 0   |
+-----+-----+
with 
    m   as(
    select 
        max(MON) as MON,
        ...
        max(SUN) as SUN
    from amounts 
    )
   ,t(v) as(
    select MON from m
    union
    select TUE from m
    union ... 
    select SUN from m
)
select max(v)
from t
select MAX(dayvalues.v)
from 
amounts          
CROSS APPLY (VALUES  (amounts.MON),(amounts.TUE),(amounts.WED),(amounts.THU),
                     (amounts.FRI),(amounts.SAT),(amounts.SUN)
            ) dayvalues(v)
我需要从上面的行中获取
MAX()
值(该表只有一行)

我怎样才能将表透视成这样:

// structure 1
+-----+-----+-----+-----+-----+-----+-----+
| MON | TUE | WED | THU | FRI | SAT | SUN |
+-----+-----+-----+-----+-----+-----+-----+
| 1   | 6   | 3   | 1   | 1   | 3   | 0   |
+-----+-----+-----+-----+-----+-----+-----+
// structure 2
+-----+-----+
| DAY | AMT |
+-----+-----+
| MON | 1   |
+-----+-----+
| TUE | 6   |
+-----+-----+
| WED | 3   |
+-----+-----+
| THU | 1   |
+-----+-----+
| FRI | 1   |
+-----+-----+
| SAT | 3   |
+-----+-----+
| SUN | 0   |
+-----+-----+
with 
    m   as(
    select 
        max(MON) as MON,
        ...
        max(SUN) as SUN
    from amounts 
    )
   ,t(v) as(
    select MON from m
    union
    select TUE from m
    union ... 
    select SUN from m
)
select max(v)
from t
select MAX(dayvalues.v)
from 
amounts          
CROSS APPLY (VALUES  (amounts.MON),(amounts.TUE),(amounts.WED),(amounts.THU),
                     (amounts.FRI),(amounts.SAT),(amounts.SUN)
            ) dayvalues(v)
。。。然后选择
AMT
列的
MAX()
值:

SELECT MAX(AMT)
FROM (
    SELECT * FROM amounts
) AS amts
PIVOT (
    AMT FOR * IN ... // got stuck here, pivots are confusing
) AS highest_amt

有更有效的方法吗?

实际上是
unpivot
而不是
pivot

透视-从行到列

UnPivot-从列到行

试试这个

CREATE TABLE #temp
  (
     MON INT,
     TUE INT,
     WED INT,
     THU INT,
     FRI INT,
     SAT INT,
     SUN INT
  )

INSERT INTO #temp
VALUES     (1,2,3,4,5,6,7)

SELECT *
FROM   #temp

;WITH cte
     AS (SELECT value,
                col,
                Row_number()
                  OVER(
                    ORDER BY value DESC) rn
         FROM   #temp
                UNPIVOT ( value
                        FOR col IN (MON,
                                    TUE,
                                    WED,
                                    THU,
                                    FRI,
                                    SAT,
                                    SUN ) ) unpiv)
SELECT value,
       COL AS AMT
FROM   cte
WHERE  rn = 1 

我能想象的最有效的方法是分别最大化每一列,然后并集以获得最大值

with t(v) as(
    select max(MON) from amounts 
    union
    select max(TUE) from amounts 
    union ... 
    select max(SUN) from amounts 
)
select max(v)
from t
可以这样改进:

// structure 1
+-----+-----+-----+-----+-----+-----+-----+
| MON | TUE | WED | THU | FRI | SAT | SUN |
+-----+-----+-----+-----+-----+-----+-----+
| 1   | 6   | 3   | 1   | 1   | 3   | 0   |
+-----+-----+-----+-----+-----+-----+-----+
// structure 2
+-----+-----+
| DAY | AMT |
+-----+-----+
| MON | 1   |
+-----+-----+
| TUE | 6   |
+-----+-----+
| WED | 3   |
+-----+-----+
| THU | 1   |
+-----+-----+
| FRI | 1   |
+-----+-----+
| SAT | 3   |
+-----+-----+
| SUN | 0   |
+-----+-----+
with 
    m   as(
    select 
        max(MON) as MON,
        ...
        max(SUN) as SUN
    from amounts 
    )
   ,t(v) as(
    select MON from m
    union
    select TUE from m
    union ... 
    select SUN from m
)
select max(v)
from t
select MAX(dayvalues.v)
from 
amounts          
CROSS APPLY (VALUES  (amounts.MON),(amounts.TUE),(amounts.WED),(amounts.THU),
                     (amounts.FRI),(amounts.SAT),(amounts.SUN)
            ) dayvalues(v)
更新

根据@PanagiotisKanavos的评论,我意识到SQL SERVER将运行同一视图7次。但在其他数据库管理系统中,如ORACLE,只需先进行一次表扫描就可以聚合7列,这确实可以为这种情况节省时间

幸运的是,在SQL SERVER中,
values
子句可以做到这一点,聚合后连接7列比聚合前交叉连接更有效。您可以使用比较查询计划


您不需要取消打印结果。在您的情况下,如果结果来自报告视图,这可能会导致执行计划效率低下

您可以使用
VALUES
构造函数从视图的列中创建一个值表,然后获得如下所示的最大值:

// structure 1
+-----+-----+-----+-----+-----+-----+-----+
| MON | TUE | WED | THU | FRI | SAT | SUN |
+-----+-----+-----+-----+-----+-----+-----+
| 1   | 6   | 3   | 1   | 1   | 3   | 0   |
+-----+-----+-----+-----+-----+-----+-----+
// structure 2
+-----+-----+
| DAY | AMT |
+-----+-----+
| MON | 1   |
+-----+-----+
| TUE | 6   |
+-----+-----+
| WED | 3   |
+-----+-----+
| THU | 1   |
+-----+-----+
| FRI | 1   |
+-----+-----+
| SAT | 3   |
+-----+-----+
| SUN | 0   |
+-----+-----+
with 
    m   as(
    select 
        max(MON) as MON,
        ...
        max(SUN) as SUN
    from amounts 
    )
   ,t(v) as(
    select MON from m
    union
    select TUE from m
    union ... 
    select SUN from m
)
select max(v)
from t
select MAX(dayvalues.v)
from 
amounts          
CROSS APPLY (VALUES  (amounts.MON),(amounts.TUE),(amounts.WED),(amounts.THU),
                     (amounts.FRI),(amounts.SAT),(amounts.SUN)
            ) dayvalues(v)
VALUES
将根据
amounts
中的值创建一个表,然后
MAX
将选择最大值<代码>交叉应用将其右侧的表值函数(值)应用于左侧的每一行


这意味着该视图只执行一次

在google中有大量答案!!如果您有超过一行,您希望得到什么?您要查找的操作员称为
UNPIVOT
btw@PanagiotisKanavos,amounts表中只有一行,它实际上是为报告而创建的视图purposes@proPhet这意味着有大量数据聚合到一行。在这种情况下,取消激励可能会导致执行计划效率低下。数据来自报告视图。这会很糟糕performance@PanagiotisKanavos第二个sql呢?最糟糕的可能是,您仍然运行同一个视图7次(每个联合一次)。添加聚合充其量也无济于事,因为视图只返回一行already@PanagiotisKanavos很抱歉,我没有在SQLServer中检查查询计划,但它在其他DBMS(如ORACLE和DB2)中确实有效。我找到了另一个解决方案并更新了我的答案,我认为这种方式确实更好。你确定其他RDBMS吗?它们中的查询优化器都必须决定如何处理7个必须联合的不同聚合操作。他们中会有人将其转换为单个聚合吗?这并不是说SQL Server很笨(实际上它有一个更好的优化器),而是在一个视图上强制执行多个聚合,而不检查结果的执行工厂。数据来自报告视图。取消激活它可能会导致性能下降,如果它干扰视图的执行计划。这是一种优雅、高效的方法,适用于任意数量的行,不像这里的其他答案。