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 ピボット テーブルまたは DevExpress Pivot Grid などのサード パーティ コンポーネントを介して、最初の結果セット (UNION クエリの出力) で停止できることを意味します)。

于 2012-09-15T09:02:33.517 に答える
6

1 つの動的ビルド 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

これが最終結果です。

ここに画像の説明を入力

これがあなたにとって意味があることを願っています。そして、たった1つのステートメントでこれを行うことができなかったことに本当に失望しています. もし誰でもできるなら、それは非常に興味深いテクニックです。

私があなたなら、このコード ストア プロシージャから、列内のテキストの最小長とユーザー ID をパラメーターとして作成します。

于 2012-09-15T17:41:05.157 に答える