【问题标题】:select column name from max query从最大查询中选择列名
【发布时间】:2011-04-20 01:10:26
【问题描述】:

我有一个类似这样的查询:

 ;WITH t as
(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1],  20 as [Col2],  20 as [Col3],  20 as [Col4] UNION ALL
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1],  30 as [Col2],  40 as [Col3],  50 as [Col4]
)
SELECT  RowNumber, ObjectID,
        (
        SELECT  MAX(Amount)
        FROM    (
                SELECT  [Col1] AS Amount
                UNION ALL
                SELECT  [Col2]
                UNION ALL
                SELECT  [Col3]
                UNION ALL
                SELECT  [Col4]
                ) d
       WHERE   Amount > 0
        )
FROM    t

查询工作正常,但我想知道 Max(Amount) 来自哪里。

因此,在我的结果集中,除了具有 (RowNumber, ObjectId, Amount) 之外,我还希望将列的名称 (Col1, Col2, Col3, Col4) 作为字符串。

有什么办法吗?

编辑 cmets 的问题:如果两列具有相同的最大值,它可能是任何一个?是的,它可以是任何一个。只要我知道它可能来自哪里,任何列名都可以。

使用 SQL Server 2008

【问题讨论】:

  • 如果 Col1 和 Col2 有相同的 MAX 怎么办:它可能是任何一个......?
  • 希望您不介意我刚刚编辑了您的代码以使其成为可运行的示例,因为我以前从未见过这种方法。随意回滚!
  • @Martin:我对编辑很好。让人们更容易回答。谢谢你。

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


【解决方案1】:

不要 MAX:使用 TOP 以避免聚合/GROUP BY。

它还可以使用 WITH TIES 处理重复项

我不确定您拥有的是伪代码还是子查询,但这应该可以满足您的需求

 SELECT TOP 1 -- WITH TIES if needed
     *
 FROM
     (
     SELECT  RowNumber, ObjectID, [Col1] AS Amount, 'Col1' AS ColName
     FROM table
     UNION ALL
     SELECT  RowNumber, ObjectID, [Col2], 'Col2' AS ColName
     FROM table
     UNION ALL
     SELECT  RowNumber, ObjectID, [Col3], 'Col3' AS ColName
     FROM table
     UNION ALL
     SELECT  RowNumber, ObjectID, [Col4], 'Col4' AS ColName
     FROM table
     ) foo
 WHERE   Amount > 0
 ORDER BY Amount DESC

您的主要问题是,无论您如何操作,您都必须触摸表格 4 次,因为子查询只返回一个值。我也看不到 ROW_NUMBER 解决方案(但可能有一个... :-)

【讨论】:

  • 他的查询是按行执行的。我从来不知道你能做到。
  • @Martin Smith:它有效,但我也不确定如何获取列名,因为它是只允许一个值的子查询。请参阅以下链接:sqlblogcasts.com/blogs/simons/archive/2006/05/08/…sqlblogcasts.com/blogs/simons/archive/2006/05/16/…
  • 是的,以前从未见过。感谢您的链接!
  • 感谢您的帮助。这是一个子查询,完整的查询比这更长,并且有超过 4 列我可以得到它的名称。这个查询不会一遍又一遍地运行,所以我不担心效率。我只想要准确的结果。如果我能让它像那样工作,将在完整查询中尝试您的解决方案并标记为已接受。
  • +1。我也从未见过这种类型的列引用。
【解决方案2】:

这是未经测试的:但是要查看您的数据发生了什么,这可能会有所帮助。不是真正的生产代码质量:

SELECT  RowNumber, ObjectID,
        (
        SELECT  MAX(Amount)
        FROM    (
                SELECT str([Col1]) + ", col1, " AS Amount
                UNION ALL
                SELECT str([Col2]) + ", col2" 
                UNION ALL
                SELECT str([Col3]) + ", col3"
                UNION ALL
                SELECT str([Col4]) + ", col4"
                )
        WHERE   Amount > 0
        )
FROM    table

str() 是 DBMS 的“toString()”函数。 您的 SQL 看起来很奇怪,您使用的是什么 DBMS?

【讨论】:

  • 你必须有 Amount > '0' 但这很整洁 + 1
  • 这是一个聪明的做法。没有考虑将列名附加为这样的字符串。谢谢
【解决方案3】:

user202553's answer添加一个步骤

;WITH t1 as(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1],  20 as [Col2],  20 as [Col3],  20 as [Col4] UNION ALL
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1],  30 as [Col2],  40 as [Col3],  50000045 as [Col4]
),
t2 as(
SELECT  RowNumber, ObjectID,
        (
        SELECT  TOP 1 CAST(C AS BINARY(4)) + CAST(Amount as BINARY(4)) 
        FROM    (
                SELECT 'Col1' AS C, [Col1] AS Amount
                UNION ALL
                SELECT 'Col2' AS C, [Col2]
                UNION ALL
                SELECT 'Col3' AS C, [Col3]
                UNION ALL
                SELECT 'Col4' AS C, [Col4]
                ) d
       WHERE   Amount > 0
       ORDER BY Amount desc
        ) AS Top1
FROM    t1
)
SELECT RowNumber, 
       ObjectID,
       CAST(Left(Top1, 4) AS CHAR(4)) AS Col, 
       CAST(SUBSTRING(Top1,5,4) AS INT) AS Amount
FROM t2

【讨论】:

  • 谢谢,也很干净
  • 比字符串连接更简洁:固定长度“编码”
【解决方案4】:

您可以使用UNPIVOTOUTER APPLY 的组合:

;WITH t as     (
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1],  20 as [Col2],  
       20 as [Col3],  20 as [Col4] UNION ALL
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1],  30 as [Col2],  
       40 as [Col3],  50 as [Col4] )
SELECT 
  RowNumber,
  ObjectID,
  ColName,
  ColAmount
FROM t
OUTER APPLY (
  SELECT TOP 1 
    ColName,
    ColAmount
  FROM 
    (
      SELECT
        Col1,
        Col2,
        Col3,
        Col4
    ) x 
    UNPIVOT (
      ColAmount FOR ColName IN (Col1, Col2, Col3, Col4) 
    ) y
   WHERE ColAmount > 0
   ORDER BY ColAmount DESC
 ) z

结果:

RowNumber   ObjectID    ColName   ColAmount
----------- ----------- --------- -----------
1           1           Col2      20
2           2           Col4      50

【讨论】:

  • 谢谢,这是最好的解决方案。不知道 UNPIVOT 功能,但这正是我想要的。
猜你喜欢
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
  • 2021-09-12
相关资源
最近更新 更多