在投影级别应用条件

时间:2015-03-23 02:18:15

标签: sql tsql plsql

是否有一种在投影级别应用条件的简单方法?我的意思是在一系列字段(列)中,我们如何只选择那些具有特定条件的字段?


示例:

假设我们有一个查询结果如下:

Id  Col1    Col2    Col3    Col4    Col5    Col6    Col7    Col8    Col9    Col10   Col11
-   ----    ----    ----    ----    ----    ----    ----    ----    ----    ----    ----
1   V1_1    NULL    NULL    V4_1    NULL    NULL    NULL    NULL    NULL    V10_1   NULL
2   V1_2    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    V10_2   NULL
3   V1_3    NULL    NULL    V4_3    NULL    NULL    NULL    NULL    NULL    V10_3   NULL

我们如何 select only the fields which contains none null values while we don't know which of them contains none null values ?结果就是这样:

Id  Col1    Col4    Col10
-   ----    ----    ----
1   V1_1    V4_1    V10_1
2   V1_2    NULL    V10_2
3   V1_3    V4_3    V10_3

通常我会使用硬编码执行此类查询,我可以在sys.all_obejctssys.all_columnsMsSQL Server等{{1}中查询all_tab_colsall_tables }}。并且不使用任何内容,一个或多个Oracle s,cursor语句,case,多个pivotif

示例中的

:对于T-SQL中包含上述数据的表,我可以这样做:

dynamic sql

但正如你所看到的那样,这个想法根本不常见,对这些场景做这样的编码有点困难


您是否知道这种查询的简单方法或模式?

RDBMS并不重要,对任何RDBMS来说都是一个很好的解决方案非常有用。

我希望答案一般不仅仅是我提到的例子。

1 个答案:

答案 0 :(得分:0)

这是一个T-SQL解决方案。您所要做的就是将@TargetTable更改为您想要的表格。希望这可以帮助!我评论了我的代码解释了所有内容,但如果您有任何问题,请告诉我们!

 IF OBJECT_ID('myTable') IS NOT NULL
    DROP TABLE dbo.myTable;

CREATE TABLE myTable
(
    ID INT IDENTITY(1,1),
    Col1 VARCHAR(25),
    Col2 VARCHAR(25),
    Col3 VARCHAR(25)
)


INSERT INTO dbo.myTable(Col1,Col2,Col3)
    VALUES  ('v1_1',NULL,NULL),
            ('v1_2','v2_2',NULL),
            ('v1_3',NULL,NULL);


/* Now that I've set up the problem, here's for the actual code*/
--Set your desired table
DECLARE @TargetTable VARCHAR(100) = 'myTable'

--If this global temp table exists, drop it
IF OBJECT_ID('##tempTable') IS NOT NULL
    EXEC('DROP TABLE ##tempTable');

--This is going to take one character and cast it to NCHAR(1)
    --If there are no characters, it will simply return NULL
DECLARE @AllColumns VARCHAR(MAX);

SELECT @AllColumns = COALESCE(@AllColumns + ',','') + 'CAST(LEFT(' + QUOTENAME(COLUMN_NAME) + ',1) AS NCHAR(1)) AS ' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE TABLE_NAME = @TargetTable

/*Load your char results into a global temp table*/
EXEC('SELECT ' + @AllColumns + ' INTO ##tempTable FROM ' + @TargetTable);

/*Here's where the fun beings*/

/*  @DesiredCol holds the name of columns that are not null.
    UNPIVOT the data.
    Where clause gets rid of columns with only NULL values.
    Group by only allows distinct columns.
    You the select from your ORIGINAL table, not my funky nchar(1) global temp table.
*/

EXEC(

    'DECLARE @DesiredCol VARCHAR(MAX);
    SELECT @DesiredCol = COALESCE(@DesiredCol + '','','''') + QUOTENAME(col)
    FROM ##temptable 
    UNPIVOT
    (
    val FOR col IN ([ID],[Col1],[Col2],[Col3])
    ) pvt
    WHERE pvt.val IS NOT NULL
    GROUP BY col

    EXEC (''SELECT '' + @DesiredCol + '' FROM ##' + @TargetTable + ''')'
    )
--Cleanup
IF OBJECT_ID('##tempTable') IS NOT NULL
    EXEC('DROP TABLE ##tempTable');