如何获取表格每列中的每个值的集合?

时间:2015-02-26 11:15:38

标签: sql sql-server

我有两个表,ValuesSpecialValues

Values有两列,RecordIDValueName

SpecialValues是一个包含单行的表格,以及名为SpecialValueName1SpecialValueName2SpecialValueName3等的30列。

此系统存在明显的数据库设计问题。

除此之外,有人可以向我解释如何查询SpecialValues,以便我可以从表格中获取每一行的所有值的集合,并将其从Values选择中排除吗?

可能有一些简单的方法可以做到这一点或为它创建一个View或者其他东西,但我认为看看这段代码可能暂时让我失望......

编辑:我想查询从给定表的每一行和每列中获取所有单个值(在本例中为SpecialValues表),以便查询执行下次有人将另一列添加到SpecialValues表时,无需更新。

4 个答案:

答案 0 :(得分:1)

我可能会误解,但这不是吗?

SELECT * FROM Values
WHERE ValueName NOT IN (
   SELECT SpecialValueName1 FROM SpecialValues
   UNION SELECT SpecialValueName2 FROM SpecialValues
   UNION SELECT SpecialValueName3 FROM SpecialValues
   etc..
)

您当然可以将子查询转换为视图。

*编辑:

这很难看,但应该解决你的问题:

首先创建程序#1

CREATE PROCEDURE [dbo].[SP1] 

As

DECLARE
    @Query nvarchar(MAX),
    @Table nvarchar(255),
    @Columns nvarchar(255)

CREATE TABLE #TempTable (Value nvarchar(255))

SET @Table = 'SpecialValues'

SELECT  [COLUMN_NAME]
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE [TABLE_NAME] = @Table

DECLARE Table_Cursor CURSOR FOR

    SELECT COLUMN_NAME
    FROM [INFORMATION_SCHEMA].[COLUMNS]
    WHERE [TABLE_NAME] = @Table

    OPEN Table_Cursor
    FETCH NEXT FROM Table_Cursor INTO @Columns

    WHILE @@FETCH_STATUS = 0
        BEGIN

            INSERT INTO #TempTable EXEC SP2 @Columns = @Columns, @Table = @Table

        FETCH NEXT FROM Table_Cursor INTO @Columns
        END

CLOSE Table_Cursor
DEALLOCATE Table_Cursor

SELECT ValueName FROM Value WHERE Value NOT IN (SELECT * FROM #TempTable)

TRUNCATE TABLE #TempTable
DROP TABLE #TempTable

然后创建程序#2

CREATE PROCEDURE [dbo].[SP2] 

    @Columns nvarchar(255) = '',
    @Table nvarchar(255)

AS

    DECLARE 
        @Query nvarchar(MAX)

    SET @Query = 'SELECT TOP 1 CONVERT(nvarchar, ' + @Columns + ') FROM ' + @Table

    EXEC (@Query)

然后最后执行程序

EXEC SP1

答案 1 :(得分:1)

这会创建一个@SpecialValuesColumns临时表来存储SpecialValues中的所有列名 然后,它使用游标将每个列中的所有值插入另一个临时表#ProtectedValues 然后,它会使用NOT IN查询将查询中的所有值排除到Values

这段代码很糟糕,我觉得编写它很糟糕,但它似乎是现在最开放的选择。

DECLARE @SpecialColumnsCount INT;
DECLARE @Counter INT;
DECLARE @CurrentColumnName VARCHAR(255);
DECLARE @ExecSQL VARCHAR(1024);
SET @Counter = 1;

CREATE TABLE #ProtectedValues(RecordID INT IDENTITY(1,1) PRIMARY KEY NOT NULL, Value VARCHAR(255));
DECLARE @SpecialValuesColumns TABLE (RecordID INT IDENTITY(1,1) PRIMARY KEY NOT NULL, ColumnName VARCHAR(255));

INSERT INTO @SpecialValuesColumns (ColumnName)
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE 
TABLE_NAME = 'SpecialValues' AND
DATA_TYPE = 'varchar' AND
CHARACTER_MAXIMUM_LENGTH = 255

SELECT @SpecialColumnsCount = COUNT(*) FROM @SpecialValuesColumns

WHILE @Counter <= @SpecialColumnsCount
BEGIN
    SELECT @CurrentColumnName = ColumnName FROM @SpecialValuesColumns WHERE RecordID = @Counter;
    SET @ExecSQL = 'INSERT INTO #ProtectedValues (Value) SELECT ' + @CurrentColumnName + ' FROM SpecialValues'
    EXEC (@ExecSQL)
    SET @Counter = @Counter + 1;
END

SELECT * FROM Values WHERE ValueName NOT IN (SELECT ValueName COLLATE DATABASE_DEFAULT FROM #ProtectedValues)
DROP TABLE #ProtectedValues;

答案 2 :(得分:0)

您需要取消specialvalues中的值。一种非常简单的方法是使用cross apply语法:

select sv.value
from specialvalues sv cross apply
     (values(sv.SpecialValueName1), (sv.SpecialValueName2), . . . 
     ) sv(value)
where sv.value is not null;

您可以使用not innot existsleft join从列表中排除这些内容。

答案 3 :(得分:0)

你有什么方法可以剪切它,你必须在SpecialValues中指定列,你可以使用一长串UNION个查询来执行此操作,或者使用UNPIVOT

select SpecialValue
from (select SpecialValueName1,SpecialValueName2,SpecialValueName3 from #SpecialValues) p
unpivot (SpecialValue FOR ROW IN (SpecialValueName1,SpecialValueName2,SpecialValueName3))
AS unpvt

然后,您可以使用Values

将其合并到NOT IN的查询中
select * from [Values] where ValueName not in (
    select SpecialValue
    from (select SpecialValueName1,SpecialValueName2,SpecialValueName3 from #SpecialValues) p
    unpivot (SpecialValue FOR ROW IN (SpecialValueName1,SpecialValueName2,SpecialValueName3))
    AS unpvt
)