可能会问类似问题,但我无法找到符合我需求的任何内容.
如何仅选择字符串长度大于2的列
这已经做了多少.
SELECT * FROM Table1
WHERE (Table1.ID = @ID)
Run Code Online (Sandbox Code Playgroud)
或类似的东西
WHERE (Table1.ID = @ID) AND (LEN(*) > 2)
Run Code Online (Sandbox Code Playgroud)
感谢您的所有帮助
我有一个表,其中我有35列和一个用户ID列,现在我想从只有> 2字符串的列中选择和显示信息.
我喜欢只选择具有> 2字符串和用户定义的ID而不是整行的列!
我希望我有意义.
表

期望的结果

GIANT EDIT
虽然我同意@ Joro的方法,但我意识到有一种稍微冗长但更简单的方法.
我创建了一个表的副本并将其命名为Lessons,但我只在其中放入了12个Lessons,但您可以以相同的方式生成查询.
使用以下查询(使用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'
Run Code Online (Sandbox Code Playgroud)
我生成一个看起来像这样的查询:
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
Run Code Online (Sandbox Code Playgroud)
通过将@ID声明为35来删除最后一个UNION并运行查询,这给了我:
|| ID || LessonName || Lesson
|| 35 || Lesson 4 || Maths
|| 35 || Lesson 9 || ICT
|| 35 || Lesson 12 || English
Run Code Online (Sandbox Code Playgroud)
然后我自己想,好吧,我可能只是使用上面的技术来调整它...但是我有另一个 - 我们实际想要的列是在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
Run Code Online (Sandbox Code Playgroud)
这给了我结果 '[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
Run Code Online (Sandbox Code Playgroud)
哪个回报:
|| ID || Lesson 4 || Lesson 9 || Lesson 12
|| 35 || Maths || ICT || English
Run Code Online (Sandbox Code Playgroud)
使用pivot函数的另一种方法 - 您可以轻松生成此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
Run Code Online (Sandbox Code Playgroud)
哪个会给你你想要的答案.
请注意,在GUI级别转动数据(通过Excel Pivot表或第三方组件,如DevExpress Pivot Grid,意味着您可以停在第一个结果集 - UNION查询的输出)
我还没有设法只使用一个动态构建的T-SQL语句.以下是您应该做的以获得所需的结果:
创建临时表来存储结果:
DECLARE @DynamicSQLStatement NVARCHAR(MAX)
CREATE TABLE #DataSource
(
[Id] BIGINT
,[SubjectName] NVARCHAR(100)
,[Lesson] NVARCHAR(100)
)
Run Code Online (Sandbox Code Playgroud)
使用特定数据初始化临时表:
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
Run Code Online (Sandbox Code Playgroud)
现在,我们在其中有这些记录:

请注意限制结果的"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'
Run Code Online (Sandbox Code Playgroud)
这是最后一个 - 以期望格式获取结果并删除临时表:
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
Run Code Online (Sandbox Code Playgroud)
这是最终的结果:

我希望这对你有意义.我真的很失望,我只能通过一个声明来做到这一点.如果有人能够,那将是非常有趣的技术.
如果我是你,我将从这个代码存储过程中使用参数创建列和用户ID中文本的最小长度.