MSSQL从25列中选择最低但不是NULL / 0值

时间:2018-02-06 10:30:25

标签: sql sql-server

我在MSSQL的一个表中有25个(数字)列,我需要选择最低值,但不是NULL或0值。

列的名称类似于"%_ price" (aaa_price,bbb_price,ccc_price ......)。 有些列包含0或NULL值。

示例:

table (aaa_price, bbb_price, ccc_price, ddd_price, eee_price, fff_price)
value (NULL,      0,         324.23,    162.50,    NULL,      1729.72  )

正确的结果: 的 162.50

我可以使用一些"蛮力"方法如:

SELECT CASE
    WHEN Col1 <= Col2 AND Col1 <= Col3 AND Col1 <= Col4 AND Col1 <= Col5 THEN Col1
    WHEN                  Col2 <= Col3 AND Col2 <= Col4 AND Col2 <= Col5 THEN Col2
    WHEN                                   Col3 <= Col4 AND Col3 <= Col5 THEN Col3
    WHEN                                                    Col4 <= Col5 THEN Col4
    ELSE                                                                      Col5
END AS [Min Value] FROM [Your Table]

但它有25列的疯狂......还有更好的解决方案吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

在这种情况下,

Cross apply可能是不错的选择:

select
    *
from
    myTable
    cross apply (select 
                    minVal = min(val) 
                from (
                    values (aaa_price),(bbb_price),(...)
                ) t(val) where val > 0
    ) q

编辑: 如果要从INFORMATION_SCHEMA.COLUMNS表中获取列名,则必须使用动态SQL。

declare @sql varchar(8000)
declare @cols varchar(8000)

select @cols =
    stuff((
        SELECT 
            ',(' + COLUMN_NAME + ')'
        FROM 
            INFORMATION_SCHEMA.COLUMNS 
        WHERE 
            TABLE_NAME = 'mytable' 
            AND TABLE_SCHEMA='dbo' 
            AND COLUMN_NAME LIKE '%price'
        for xml path('')
    ), 1, 1, '')

set @sql = 'select
                *
            from
                mytable
                cross apply (select 
                                minVal = min(val) 
                            from (
                                values ' + @cols + '
                            ) t(val) where val > 0
                ) q'

exec (@sql)

答案 1 :(得分:1)

您可以创建dynamic SQL statement并按以下格式执行

declare @tablename sysname = 'MultipleNumericColumns'
declare @sql nvarchar(max) 

select @sql = isnull(@sql + ' union all ','') + '
SELECT ' + name + ' as colname from ' + @tablename  
from sys.all_columns 
where 
    object_id = OBJECT_ID(@tablename)

set @sql = '
select min(colname)
from (
' + @sql + '
) t
where colname > 0'

EXECUTE(@sql)

你可以意识到我首先从系统视图中获取列名

您可以在此步骤中排除您不想要的列或使用类似&#39;%price%等名称的模式

然后我将一个动态SQL查询构建为一个字符串变量作为sql命令 请注意,我使用大于0的WHERE子句等

最后一步是使用EXECUTE命令执行

答案 2 :(得分:0)

使用let apiVersions = ["2017-10-01", "2017-06-01", "2016-12-01", "2016-05-01", "2016-01-01"]; describe("put", function () { it("should create a storage account with storage account type, async () => { for (const apiVersion of apiVersions) { let location = 'uk south'; let resourceGroupName = 'test'; let storageAccountName = 'stacct'; AzureAuthentication.StorageAccountApiVersion = apiVersion; // StorageAccount.FormatName(storageAccountName + apiVersion): this function will give me string without special charaters and spaces etc, e.g stacct20171001 await StorageAccount.CreateStorageAccount(resourceGroupName, location, StorageAccount.FormatName(storageAccountName + apiVersion), AzureAuthentication); } }); });

UNPIVOT