こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

テーブルの項目名を変数にするには?

<開発環境>
WindowsXP Professional
SQL Server 2005

いつもお世話になっております。
次のようなことをやりたいのですが、上手くできず困っています。
どなたかご教示くださると助かります。

○やりたいこと
 テーブルの項目数が1~200個あり、項目名が「ユーザ数001」「アクセス回数001」~
「ユーザ数100」「アクセス回数100」の順に並んでいる。
そこで、変数を使って「ユーザ数001」~「ユーザ数100」と
「アクセス回数001」~「アクセス回数100」にSELECTして得られた
結果をINSERTしたい。

テーブルの列名(項目名)は以下のようにして取得することはできました。

SELECT dbo.syscolumns.name FROM dbo.syscolumns INNER JOIN dbo.sysobjects ON (dbo.sysobjects.id = dbo.syscolumns.id)
WHERE dbo.sysobjects.name = 'テーブル名'
AND (dbo.syscolumns.name LIKE '%ユーザ数%' + @cnt
OR dbo.syscolumns.name LIKE '%アクセス回数%' + @cnt)

@cntは変数で1~100までカウントアップして列名を取得しています。

○困っていること

・上記のSELECTで得られた結果を別の変数「@User」「@Access」にセットしたいが上手くできない。
・さらに「@User」「@Access」を使って、INSERTを行いたい。
(具体的には以下のようにしたい)
INSERT INTO dbo.[テーブル名](@User,@Access)
SELECT TOP 100
UCNT,
ACNT
FROM (
SELECT・・・

(このINSERT文は前後にWHILE文で1~100まで処理を回して、変数「@cnt」がカウントアップするようにしています)

以上、下手な説明でわかりにくいかもしれませんが、宜しくお願い致します。

投稿日時 - 2009-08-19 03:21:59

QNo.5218630

困ってます

このQ&Aは役に立ちましたか?

10人が「このQ&Aが役に立った」と投票しています

-広告-
-広告-

回答(4)

ANo.4

#2,#3です。

>jamshid6さんのおっしゃるとおり、200列すべてに件数がセットされた「1行」のデータが作りたいのですが、、、
ですよね。INSERTを100回ループさせると100行になりますからね。
したがって、1回目だけINSERTで、2回目以降はUPDATEになります。

DECLARE @cnt int
DECLARE @sql varchar(max)

SET @cnt = 1
WHILE (@cnt<=100)
BEGIN
IF (@cnt=1)
 SET @sql='
  INSERT INTO [テーブル名]
  (ユーザ数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+',
  アクセス回数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+')
  SELECT
  UCNT,
  ACNT
  FROM (
  SELECT・・・'
ELSE
 SET @sql='
 UPDATE t1
 SET ユーザ数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+'=t2.UCNT,
   アクセス回数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+'=t2.ACNT
 FROM [テーブル名] t1
 CROSS JOIN (
   SELECT UCNT,ACNT
   FROM (
   SELECT・・・) t2'

 EXEC (@sql)
 SET @cnt=@cnt+1
END

ただ、私だったらおそらく上記のようにはやりません。
なぜなら、詳細が示されていないですが、(SELECT・・・以下のクエリはたぶん100回ループしなくても一気に件数が取れるタイプのものだろうと推測しているからです。
例えば、
SELECT
SUM(CASE WHEN 条件x=1 THEN 1 ELSE 0 END) UCNT001,
SUM(CASE WHEN 条件y=1 THEN 1 ELSE 0 END) ACNT001,
SUM(CASE WHEN 条件x=2 THEN 1 ELSE 0 END) UCNT001
SUM(CASE WHEN 条件y=2 THEN 1 ELSE 0 END) ACNT002,
・・・
FROM (
SELECT ・・・)
のような書き換えができるのではありませんか?
(条件が@cntと連動していなければ、100回ループは実現できませんよね)

その場合は、ループの対象をクエリの実行ではなく、SQL文の組立ての方にして、以下のように一発でINSERTできます。
(100回更新クエリを実行するよりいいはずです)

DECLARE @cnt int
DECLARE @sql varchar(max)
SET @cnt=1
WHILE (@cnt<=100)
BEGIN
 SET @sql=ISNULL(@sql+',','')
  +'SUM(CASE WHEN 条件x='+CONVERT(varchar,@cnt)+' THEN 1 ELSE 0 END),'
  +'SUM(CASE WHEN 条件y='+CONVERT(varchar,@cnt)+' THEN 1 ELSE 0 END)'
 SET @cnt=@cnt+1
END
SET @sql='INSERT INTO [テーブル名] SELECT '+@sql+' FROM (SELECT ・・・) tmp'
EXEC (@sql)

まあ、状況については多分に推測が入っていますので、考え方の参考として応用してみてください。

投稿日時 - 2009-08-21 12:20:34

お礼

>jamshid6さん

返事が遅くなってしまい、大変申し訳ありませんでした。
教えていただいたコードを参考にし、うまくできるようになりました!
わかりやすい例を提示して戴き、ありがとうございました。

また次の機会がありましたら宜しくお願い致します。

投稿日時 - 2009-08-26 02:08:51

ANo.3

#2です。

>100回ループすることで、1回目は「ユーザ数001」「アクセス回数001」の列に値をセット、
>2回目は「ユーザ数002」「アクセス回数002」の列に値をセットしたいのです。

200列すべてに件数がセットされた「1行」のデータが作りたいのではないかと思ったのですが、
そうではないということですね(2列ずつ件数が入ったデータが100行欲しいと。)

この構造でテーブルから列名を取ることにあまり意味がないと書いた理由は、以下のサンプルを見て
頂ければ分かると思います。
ちなみにこれが「動的クエリ」のサンプルです(全角スペース使ってネストしてあります)。

DECLARE @cnt int
DECLARE @sql varchar(max)

SET @cnt = 1
WHILE (@cnt<=100)
BEGIN
SET @sql='
 INSERT INTO [テーブル名]
 (ユーザ数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+',
 アクセス回数'+RIGHT('000'+CONVERT(varchar,@cnt),3)+')
 SELECT
 UCNT,
 ACNT
 FROM (
 SELECT・・・'

 EXEC (@sql)
 SET @cnt=@cnt+1
END

投稿日時 - 2009-08-20 23:14:50

補足

>jamshid6さん

再度のご回答ありがとうございます。
またしても自分の説明が下手で意図が伝わりにくくてすいません。

jamshid6さんのおっしゃるとおり、200列すべてに件数がセットされた「1行」のデータが作りたいのですが、、、
(何度もご指示を仰ぐようで大変申し訳ありません)

動的クエリのサンプルは大変参考になります。
わかりやすく教えていただきありがとうございます。

また貴重なお時間をいただくことになるかもしれませんが、宜しくお願い致します。

投稿日時 - 2009-08-21 02:06:14

ANo.2

テーブルの列名を変数にすることはできません。
どうしてもやりたい場合は動的クエリにするしかないです。

それにしても、
・質問者さんのやろうとしている方法では、1行に2列ずつしか入らず、100回ループしても100行になってしまうと思いますが、それが想定した結果なのですか?(後で結局100列分書いてグルーピングするのですか?)
・書かれたように@cntでカウントアップしているならば、そもそもsyscolumnから列をとる意味ってないように思いますが(テーブルの内容が仮に想定通りでなくても、結局INSERT文でコケてしまう)、狙いはなんでしょう?

投稿日時 - 2009-08-19 08:35:23

補足

>jamshid6さん

早速のご回答ありがとうございます。

補足説明ですが、列が1~100まであり、それぞれの列にSELECTで得られた値をセットしたいのです。
(説明が不十分ですいません)
列名を「ユーザ数001」「アクセス回数001」「ユーザ数002」「アクセス回数002」・・・「ユーザ数100」「アクセス回数100」としており、
変数を用いてテーブルの列名を取得していたのです。
(先に記述した文になります)
100回ループすることで、1回目は「ユーザ数001」「アクセス回数001」の列に値をセット、
2回目は「ユーザ数002」「アクセス回数002」の列に値をセットしたいのです。

以上、お手数をおかけしますが宜しくお願い致します。

投稿日時 - 2009-08-20 02:30:04

ANo.1

困っていることについては、
よくわからないですが、、
SELECT結果を丸ごと格納するなら、
テーブル変数の型にしないと無理なような気がします。

やりたいことについてですが、

事前に新規テーブルの項目を下記のように定義して作成しておいて、
1.[ユーザ数001],....,[ユーザ数100],...,[アクセス回数001],...,[アクセス回数100]

2.下記SQL実行

INSERT INTO [新規テーブル]
SELECT
[ユーザ数001],
.
.
.
[ユーザ数100],
[アクセス回数001],
.
.
[アクセス回数100]
FROM
[元のテーブル]

で対処できないでしょうか?
項目名をそれぞれ1~100まで入力しないといけないですが
てっとりばやいと思います。

投稿日時 - 2009-08-19 06:58:53

補足

>fantomさん

ご回答ありがとうございます。
ご指摘の通り、既に1のようにテーブルの項目は既に作成してあります。

そして、2の処理を行いたいのですが、項目数が多いので変数を使って
処理を短く記述できないものかと考えていた次第です。

変数を使ってできないとなると、fantomさんのおっしゃるとおり地道に
記述していくしかないでしょうね。

投稿日時 - 2009-08-20 02:37:19

お礼

>fantomさん

返事が遅くなってしまい、大変申し訳ありませんでした。

今回はjamshid6さんのコードを参考にし、解決に至りました。

また次の機会がありましたら宜しくお願い致します。

投稿日時 - 2009-08-26 02:11:27

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-