バイブルというか、良書および必読の書

寝ようと思っていたら、その言語で「バイブル」と呼ばれる書籍を教えてくださいなんて質問を見つけてしまい、書いてたら長くなる長くなる・・・
言語バイブル - Strategic Choiceが元らしく、いくつかかぶってるけど気にしない方向で。

ちょっと待って、本当にこんなに読まないとダメ?違うよね、絶対なんか違うよね。
むしろ、これだけ読めば OK って基準なんてないよね (何


追記:
「必読」って書いてますけど、「これ読まなきゃ Hoge 言語のプログラマ失格!」なんてものではないです。
あと、是非本は読んで欲しいけど、必ず本から知識を得る必要はないわけで・・・
とりあえず、読んでおくとためになる、くらいに思っておいてもらえるといいかな。

*1:この本を否定してるわけじゃなくて、つかいい本なんだけど、下の本とは扱ってる部分がちょっと違う。どちらかというと、下の本を読んだ上で読むような本

*2:さらに効果的とか日本語でも言いつつ

SQL Server で文字列を全部結合したいだけなら

SQL

以下のように記述すれば出来るっぽい。

DECLARE @str AS varchar(max);
SET @str = '';
SELECT @str = @str + str FROM SomeTable;
SELECT @str;

参考:文字列を集計的に結合する(ユーザー定義関数経由で GROUP BY 対応)
カンマ区切りがしたければ、

DECLARE @str AS varchar(max);
SET @str = '';
SELECT
    -- 先頭要素にはカンマを付けない
    @str = CASE @str
             WHEN '' THEN str
                     ELSE @str + ', ' + str
           END
FROM
    SomeTable
;
SELECT @str;

とか。

でも

これはあくまで対象全部を結合するのであって、例えば、

n str
1 hoge
1 piyo
2 foo
2 bar

みたいなテーブルを、

n strs
1 hoge, piyo
2 foo, bar

のように GROUP BY することは出来ない*1
SomeTable が n 順にソートされてることが前提で、

DECLARE @str AS varchar(max);
SET @str = '';
DECLARE @n AS int;
-- ありえない数値を入れておく
SET @n = -1;
SELECT
    -- nが変わるタイミングで@strをリセット
    @str = CASE @n
             WHEN n THEN @str
                    ELSE ''
           END
  , @str = CASE @str
             WHEN '' THEN str
                     ELSE @str + ', ' + str
           END
     -- @nの更新
   , @n = n
FROM
    SomeTable
;
SELECT @n, @str;

こうすれば、

n str
2 foo, bar

は出せる*2し、@str には途中、「hoge, piyo」も入るから、あと何ひねりかすれば出来るのかもしれない。
つか、T-SQL 独自の機能使ってるんだから、これでいいじゃん、とか思わなくも無いけどね。

-- 結果格納用のテーブル変数
DECLARE @Strs AS TABLE(n int, str varchar(max));

-- nの個数
DECLARE @count AS int;
SELECT @count = COUNT(DISTINCT n) FROM SomeTable;

DECLARE @i AS int;
SET @i = 0;
WHILE @i < @count BEGIN
  DECLARE @str AS varchar(max);
  SET @str = '';
  
  -- nが@i + 1の文字列を結合
  SELECT
      @str = CASE @str
               WHEN '' THEN str
                       ELSE @str + ', ' + str
             END
  FROM
      SomeTable
  WHERE
      n = @i + 1
  ;
  
  -- @i + 1と共に結合した文字列を格納
  INSERT INTO @Strs VALUES(@i + 1, @str);
  
  SET @i = @i + 1;
END

-- 全部出力
SELECT * FROM @Strs;

n が 1 から連続してない場合、

DECLARE @Strs AS TABLE(n int, str varchar(max));
-- 連番とnの対応表
DECLARE @Ns AS TABLE(i int identity(0, 1), n int);

DECLARE @count AS int;
SELECT @count = COUNT(DISTINCT n) FROM SomeTable;

-- iは自動採番して、nはSomeTableから取ってくる
INSERT INTO @Ns(n)
  SELECT DISTINCT n FROM SomeTable
;

DECLARE @i AS int;
SET @i = 0;
WHILE @i < @count BEGIN
  -- @iに対応するnを格納
  DECLARE @n AS int;
  SELECT @n = n FROM @Ns WHERE i = @i;
  
  DECLARE @str AS varchar(max);
  SET @str = '';
  SELECT
      @str = CASE @str
               WHEN '' THEN str
                       ELSE @str + ', ' + str
             END
  FROM
      SomeTable
  WHERE
      n = @n
  ;
  INSERT INTO @Strs VALUES(@n, @str);
  SET @i = @i + 1;
END

SELECT * FROM @Strs;

CLR ユーザー定義集計関数なんてものもあるみたいだけど、正直、おおげさすぎるというかなんと言うか・・・


でもやっぱり FOLD 欲しい

*1:さっきのページではユーザ定義関数で実現してる

*2:ただ、SELECT 句が前から順に評価されるってのが保証されてるかどうか不明