2

可能会问类似的问题,但我找不到任何适合我需要的东西。

如何仅选择字符串长度大于 2 的列

这已经做了多少。

SELECT * FROM Table1

WHERE (Table1.ID = @ID)

或者类似的东西

WHERE (Table1.ID = @ID) AND (LEN(*) > 2)

感谢您的所有帮助

我有一个表,其中有 35 列和一个用户 ID 列,现在我只想从具有 > 2 个字符串的列中选择和显示信息。

我喜欢只选择具有> 2个字符串和用户定义的ID而不是整行的列!

我希望我说得通。

桌子 在此处输入图像描述

期望的结果

在此处输入图像描述

4

2 回答 2

6

巨型编辑

虽然我同意@Joro 的方法,但我意识到有一种稍微冗长但更简单的方法。

我创建了您的表的副本并将其命名为“课程”,但我只在其中放置了 12 个课程,但您可以以相同的方式生成查询。

使用以下查询(使用INFORMATION_SCHEMA.COLUMNS):

SELECT  'SELECT ID, ''' + COLUMN_NAME + ''' AS LessonName, 
        [' + COLUMN_NAME + '] AS Lesson ' +
+       'FROM Lesson WHERE ID = @ID AND LEN([' + COLUMN_NAME + ']) > 2 UNION' 

FROM    INFORMATION_SCHEMA.COLUMNS
WHERE   TABLE_NAME = 'Lesson'
AND DATA_TYPE = 'varchar'

我生成一个如下所示的查询:

SELECT ID, 'Lesson 1' AS LessonName, [Lesson 1] AS Lesson  
FROM Lesson WHERE ID = @ID AND LEN([Lesson 1]) > 2 UNION
SELECT ID, 'Lesson 2' AS LessonName, [Lesson 2] AS Lesson  
FROM Lesson WHERE ID = @ID AND LEN([Lesson 2]) > 2 UNION
... (SQL omitted for brevity)
SELECT ID, 'Lesson 12' AS LessonName, [Lesson 12] AS Lesson  
FROM Lesson WHERE ID = @ID AND LEN([Lesson 12]) > 2 UNION

删除最后一个 UNION 并通过将@ID 声明为 35 来运行查询给了我:

|| ID || LessonName || Lesson
|| 35 || Lesson 4   || Maths
|| 35 || Lesson 9   || ICT
|| 35 || Lesson 12  || English

然后我想,好吧,我可能只是使用上面的技术来调整它......但后来我有了另一个 - 我们真正想要的列在 LessonName 列中,所以,我们可能只运行一个动态 SQL 查询这些列名在:

DECLARE @ColumnList VARCHAR(MAX)

SELECT @ColumnList = COALESCE(@ColumnList + ', ','') + '[' + Lessons.LessonName + ']'

FROM ( 
SELECT ID, 'Lesson 1' AS LessonName, [Lesson 1] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 1]) > 2 UNION
SELECT ID, 'Lesson 2' AS LessonName, [Lesson 2] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 2]) > 2 UNION
...
SELECT ID, 'Lesson 12' AS LessonName, [Lesson 12] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 12]) > 2) 

AS Lessons

这给了我结果'[Lesson 4], [Lesson 9], [Lesson 12]'

反过来,您可以执行以下操作:

DECLARE @QuerySQL NVARCHAR(MAX)

SET @QuerySql = 'SELECT ' + CAST(@ID AS VARCHAR) + ' AS ID, ' + @ColumnList + ' FROM Lesson WHERE ID = @ID'

--Query actually looks like: SELECT 35 AS ID, [Lesson 4], [Lesson 9], [Lesson 12] 
--                           FROM Lesson WHERE ID = 35  

DECLARE @ID INT --You will already have done this above anyway really
SET @ID = 35    

EXEC sp_executeSQL @QuerySql,N'@ID int', @ID

返回:

|| ID || Lesson 4 || Lesson 9 || Lesson 12 
|| 35 || Maths    || ICT      || English

使用数据透视函数的另一种方法 - 您可以轻松地生成此 sql 一次并将其保留在存储过程中。

因此,总而言之,您的用法如下所示:

DECLARE @ID INT
SET @ID = 35

DECLARE @ColumnList VARCHAR(MAX)

SELECT @ColumnList = COALESCE(@ColumnList + ', ','') + '[' + Lessons.LessonName + ']' 

FROM (  
SELECT ID, 'Lesson 1' AS LessonName, [Lesson 1] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 1]) > 2 UNION 
SELECT ID, 'Lesson 2' AS LessonName, [Lesson 2] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 2]) > 2 UNION 
... 
SELECT ID, 'Lesson 35' AS LessonName, [Lesson 35] AS Lesson  FROM Lesson WHERE ID = @ID AND LEN([Lesson 35]) > 2)  

AS Lessons --Remember you can generate this section quite simply using information_schema.columns
           --and you don't actually need the ID or Lesson columns - just the lesson names.

DECLARE @QuerySQL NVARCHAR(MAX) 

SET @QuerySql = 'SELECT ' + CAST(@ID AS VARCHAR) + ' AS ID, ' + @ColumnList + ' FROM Lesson WHERE ID = @ID'     

EXEC sp_executeSQL @QuerySql,N'@ID int', @ID 

这会给你你想要的答案。

请注意,在 GUI 级别旋转数据(通过 Excel Pivot 表或 DevExpress Pivot Grid 等第 3 方组件意味着您可以在第一个结果集 - UNION 查询的输出处停止)

于 2012-09-15T09:02:33.517 回答
6

我还没有设法仅使用一个动态构建的 T-SQL 语句来做到这一点。为了获得期望的结果,您应该执行以下操作:

创建临时表来存储结果:

DECLARE @DynamicSQLStatement NVARCHAR(MAX)

CREATE TABLE #DataSource
(
     [Id] BIGINT 
    ,[SubjectName] NVARCHAR(100)
    ,[Lesson] NVARCHAR(100)
)

使用特定数据初始化临时表:

SET @DynamicSQLStatement=N' INSERT INTO #DataSource ([Id],[SubjectName],[Lesson])
                            SELECT   [Id]
                                    ,[SubjectName]
                                    ,[Lesson]
                            FROM SourceTable
                            UNPIVOT 
                            (
                                [SubjectName] FOR [Lesson] IN ('+(SELECT SUBSTRING((SELECT '],[' + COLUMN_NAME FROM INFORMATION_SCHEMA.Columns  WHERE TABLE_NAME = 'SourceTable' AND COLUMN_NAME<>'ID' FOR XML PATH('')),3,300)+']')+')
                            ) as pvt
                            WHERE ID=35 AND LEN([SubjectName])>2'

EXECUTE sp_executesql @DynamicSQLStatement

现在,我们有这些记录:

在此处输入图像描述

请注意限制结果的“WHERE”子句。此外,“SourceTable”应替换为您的表的名称。我正在做的是在没有“Id”的情况下获取该表的所有列,但是您可以在没有 sp_exetuesql 的情况下执行此操作,只需写下所有列:

INSERT INTO #DataSource ([Id],[SubjectName],[Lesson])
SELECT   [Id]
        ,[SubjectName]
        ,[Lesson]
FROM SourceTable
UNPIVOT 
(
    [SubjectName] FOR [Lesson] IN ([Lesson 1],[Lesson 2],[Lesson 3],...,[Lesson n])
) as pvt
WHERE ID=35 AND LEN([SubjectName])>2'

这是最后一个 - 以期望格式获取结果并删除临时表:

SET @DynamicSQLStatement=N' SELECT *
                            FROM #DataSource
                            PIVOT
                            (
                                MAX([SubjectName]) FOR [Lesson] IN ('+ (SELECT SUBSTRING((SELECT '],[' + Lesson FROM #DataSource FOR XML PATH('')),3,100)+']')+')
                            )AS ResultTable'

EXECUTE sp_executesql @DynamicSQLStatement

DROP TABLE #DataSource

这是最终的结果:

在此处输入图像描述

我希望这对你有意义。我真的很失望,我不能只用一个声明来做到这一点。如果有人可以,那将是非常有趣的技术。

如果我是你,我会从这个代码存储过程中使用参数创建列和用户 ID 中文本的最小长度。

于 2012-09-15T17:41:05.157 回答