MW211 EXIT

devlog
ExcelVBA/接続時間延長
2015年08月26日
ExcelVBAでADODBを使ってMSSQLに問い合わせをしたが
SQLの処理が長すぎてタイムアウトエラーとなってしまう場合
以下のようにタイムアウト時間を延長することができる。
┌──────────────────────────────────────┐
│Dim テーブル As New ADODB.Recordset                                         │
│Dim SQLコマンド As New ADODB.Command                                        │
│With SQLコマンド                                                            │
│    .CommandTimeout = 180   ' ←★接続時間延長(30秒→180秒)                 │
│    .ActiveConnection = (データベース接続情報)                              │
│    .CommandText = (SQL文)                                                  │
│End With                                                                    │
│テーブル.Open SQLコマンド                                                   │
└──────────────────────────────────────┘
但し、基本的に処理が長すぎるSQL文を見直すべきで(インデックスの追加など)
上記手段を行うのは最後の最後もしくは特例的に限定すべきである。
分類:ExcelVBA、MSSQL
MSSQL/正規表現
2015年08月25日
LIKE演算子で使える。
┌──────────────────────────────────────┐
│SELECT COUNT(*)                                                             │
│    FROM 表                                                                 │
│    WHERE [列] LIKE '[A-Z][0-9]%';                                          │
└──────────────────────────────────────┘
上記の場合は「A0」や「B1ABC」などが検索できる。
分類:MSSQL
MSSQL/sqlcmdによるCSV出力
2015年07月22日
SELECT結果をCSV出力する方法。

一番オーソドックスなのは以下の形。
┌──────────────────────────────────────┐
│sqlcmd -S . -Q "SET NOCOUNT ON SELECT * FROM [表];" -h -1 -s, -W            │
│                                                         -o 出力ファイル.csv│
└──────────────────────────────────────┘

上記だと、ヘッダ表が出力されないので自前で出力する場合は以下の通り。
┌──────────────────────────────────────┐
│echo ヘッダ1,ヘッダ2,ヘッダ3> 出力ファイル.csv                              │
│sqlcmd -S . -Q "SET NOCOUNT ON SELECT * FROM [表];" -h -1 -s, -W            │
│                                                         >> 出力ファイル.csv│
└──────────────────────────────────────┘

ヘッダ出力を自動化するのなら、以下のような感じか。
┌──────────────────────────────────────┐
│sqlcmd -S . -Q "SET NOCOUNT ON SELECT * FROM [表] WHERE 1 <> 1;"            │
│                                 -h1 -s, -W | find /V "--"> 出力ファイル.csv│
│sqlcmd -S . -Q "SET NOCOUNT ON SELECT * FROM [表];" -h -1 -s, -W            │
│                                                         >> 出力ファイル.csv│
└──────────────────────────────────────┘
出力結果の最初の一行目のみ抽出もしくは最後の一行目のみ削除ってのを
Windowsコマンド上でできればいいのだが、難しいので断念。
分類:MSSQL
MSSQL/ピボット表
2015年07月10日
こんな感じ。
┌──────────────────────────────────────┐
│SELECT ISNULL(CONVERT(varchar, [群]), '計') AS [群],                        │
│       ISNULL([縦]                  , '計') AS [縦],                        │
│       SUM([横1])   AS [横1],                                             │
│       SUM([横2])   AS [横2],                                             │
│       SUM([横3])   AS [横3],                                             │
│       SUM([計])  AS [計]                                                   │
│    FROM (                                                                  │
│        SELECT [群],                                                        │
│               [縦],                                                        │
│               [横1],                                                      │
│               [横2],                                                      │
│               [横3],                                                      │
│               ([横1] + [横2] + [横3]) AS [計]                           │
│            FROM [表]                                                       │
│                PIVOT (COUNT([ID])                                          │
│                           FOR [区分]                                       │
│                           IN ([横1],[横2],[横3])) AS [ピボット]         │
│        UNION ALL                                                           │
│        SELECT [群D].[群],                                                 │
│               [縦D].[縦],                                                 │
│               NULL                  AS [横1],                             │
│               NULL                  AS [横2],                             │
│               NULL                  AS [横3],                             │
│               NULL                  AS [計]                                │
│            FROM (                                                          │
│                SELECT DISTINCT [群]                                        │
│                    FROM [表]                                               │
│            ) AS [群D]                                                     │
│                CROSS JOIN (                                                │
│                    SELECT DISTINCT [縦]                                    │
│                        FROM [表]                                           │
│                ) AS [縦D]                                                 │
│    ) AS [ピボットD]                                                       │
│    GROUP BY GROUPING SETS (                                                │
│                 (),                                                        │
│                 ([縦]),                                                    │
│                 ([群]),                                                    │
│                 ([群],[縦])                                                │
│             )                                                              │
│    ORDER BY [群] ASC,                                                      │
│             [縦] ASC;                                                      │
└──────────────────────────────────────┘
こんな結果になる(はず)。
┌──┬──┬──┬──┬──┬──┐
│ 群 │ 縦 │横1│横2│横3│ 計 │
├──┼──┼──┼──┼──┼──┤
│    │    │    │    │    │    │
│    ├──┼──┼──┼──┼──┤
│    │    │    │    │    │    │
│    ├──┼──┼──┼──┼──┤
│    │ 計 │    │    │    │    │
├──┼──┼──┼──┼──┼──┤
│ 計 │ 計 │    │    │    │    │
└──┴──┴──┴──┴──┴──┘
分類:MSSQL
MSSQL/列間の部分一致検索
2015年07月07日
LIKE演算子による部分一致判定を、列間で実行する場合。

意外に単純、'%'を文字列として結合してあげればよい。

列大が列小を内包しているもののみ抽出(部分一致検索)
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE 列大 LIKE '%' + 列小 + '%';                                       │
└──────────────────────────────────────┘

列大が列小を内包しているもののみ抽出(前方部分一致検索)
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE 列大 LIKE 列小 + '%';                                             │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/キャストの順番とNULL
2015年07月03日
date型の[日付]という列を、文字型(varchar(16))に型変換する時に
NULLが混じっていたら空文字('')にするというSQL文
ISNULL()とCONVERT()を駆使する訳だが、順番を間違えると以下の違いが出てしまう
┌──────────────────────────────────────┐
│SELECT ISNULL(CONVERT(varchar(16), [日付]), '') FROM 表;              →NULL│
├──────────────────────────────────────┤
│SELECT CONVERT(varchar(16), ISNULL([日付], '')) FROM 表;        →1900-01-01│
└──────────────────────────────────────┘

これはdate型に空文字('')を入れると、初期値(1900-01-01)になるからだ
┌──────────────────────────────────────┐
│SELECT ISNULL([日付], '') FROM 表;                              →1900-01-01│
└──────────────────────────────────────┘

一番単純な例は以下(空文字('')をdate型に型変換するとやはり初期値になる)
┌──────────────────────────────────────┐
│SELECT CONVERT(date, '');                                       →1900-01-01│
└──────────────────────────────────────┘

なので、順番を間違えないように気をつけなければならない
分類:MSSQL
MSSQL/FORMAT()とNULL
2015年07月02日
FORMAT()の引数にNULL直書きはエラーとなる
┌──────────────────────────────────────┐
│SELECT FORMAT(NULL,'0');                                                    │
│                 →引数のデータ型 NULL は format 関数の引数 1 では無効です。│
└──────────────────────────────────────┘

これはFORMAT()がNULLを許容していないのではなく、
型が不定なNULLを許容していないのだ

つまり、以下だとOK
┌──────────────────────────────────────┐
│SELECT FORMAT(CAST(NULL AS int),'0');                                 →NULL│
└──────────────────────────────────────┘

なので、テーブル上のNULLデータの場合は、テーブル定義で型も決まっているので
エラーとはならない

デバッグでうっかり勘違いしてしまいがちなところだ
分類:MSSQL
MSSQL/累積列の作り方
2015年06月26日
[+表]と[-表]を統合して時系列で二列に並べて累積を逐一計算する場合は、
以下のような感じ
┌──────────────────────────────────────┐
│SELECT [±表].[日付],                                                       │
│       CASE [±表].[±区分]                                                 │
│         WHEN 1 THEN '+'                                                   │
│         WHEN 2 THEN '-'                                                   │
│       END AS [区分],                                                       │
│       [±表].[+値],                                                       │
│       [±表].[-値],                                                       │
│       ISNULL((                                                             │
│           SELECT SUM([+表].[値])                                          │
│               FROM [+表]                                                  │
│               WHERE [+表].[日付] < [±表].[日付]                          │
│                  OR  ([+表].[日付]   =  [±表].[日付]                     │
│                   AND [+表].[±区分] <= [±表].[±区分])                  │
│       ), 0) - ISNULL((                                                     │
│           SELECT SUM([-表].[値])                                          │
│               FROM [-表]                                                  │
│               WHERE [-表].[日付] < [±表].[日付]                          │
│                  OR  ([-表].[日付]   =  [±表].[日付]                     │
│                   AND [-表].[±区分] <= [±表].[±区分])                  │
│       ), 0) AS [累積]                                                      │
│    FROM (                                                                  │
│        SELECT [日付],                                                      │
│               1         AS [±区分],                                       │
│               SUM([値]) AS [+値],                                         │
│               NULL      AS [-値]                                          │
│            FROM [+表]                                                     │
│            GROUP BY [日付]                                                 │
│        UNION ALL                                                           │
│        SELECT [日付],                                                      │
│               2         AS [±区分],                                       │
│               NULL      AS [+値],                                         │
│               SUM([値]) AS [-値]                                          │
│            FROM [-表]                                                     │
│            GROUP BY [日付]                                                 │
│    ) AS [±表]                                                             │
│    ORDER BY [±表].[日付]   ASC,                                           │
│             [±表].[±区分] ASC;                                           │
└──────────────────────────────────────┘
[-表]がなければ、もっとシンプルになる。
┌──────────────────────────────────────┐
│SELECT [±表].[日付],                                                       │
│       [±表].[+値],                                                       │
│       ISNULL((                                                             │
│           SELECT SUM([+表].[値])                                          │
│               FROM [+表]                                                  │
│               WHERE [+表].[日付] <= [±表].[日付]                         │
│       ), 0) AS [累積]                                                      │
│    FROM (                                                                  │
│        SELECT [日付],                                                      │
│               SUM([値]) AS [+値]                                          │
│            FROM [+表]                                                     │
│            GROUP BY [日付]                                                 │
│    ) AS [±表]                                                             │
│    ORDER BY [±表].[日付] ASC;                                             │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/時間を区切る
2015年06月25日
深夜残業は「22:00」以降と決まっているのだけれども
[残業開始日時]がまちまちで、[残業分]を「22:00」を境に
二つ([普通残業分]と[深夜残業分])に区切る方法。
┌──────────────────────────────────────┐
│SELECT CASE                                                                 │
│         WHEN [残業分] > DATEDIFF(MINUTE,                                   │
│                                  [残業開始日時],                           │
│                                  DATEADD(HOUR,                             │
│                                          22,                               │
│                                          CONVERT(datetime,                 │
│                                                  CONVERT(date,             │
│                                                          [残業開始日時]))))│
│         THEN                                                               │
│           DATEDIFF(MINUTE,                                                 │
│                   [残業開始日時],                                          │
│                   DATEADD(HOUR,                                            │
│                           22,                                              │
│                           CONVERT(datetime,                                │
│                                   CONVERT(date,                            │
│                                           [残業開始日時]))))               │
│         ELSE                                                               │
│           [残業分]                                                         │
│       END AS [普通残業分]                                                  │
│       CASE                                                                 │
│         WHEN [残業分] > DATEDIFF(MINUTE,                                   │
│                                  [残業開始日時],                           │
│                                  DATEADD(HOUR,                             │
│                                          22,                               │
│                                          CONVERT(datetime,                 │
│                                                  CONVERT(date,             │
│                                                          [残業開始日時]))))│
│         THEN                                                               │
│           [残業分] - DATEDIFF(MINUTE,                                      │
│                               [残業開始日時],                              │
│                               DATEADD(HOUR,                                │
│                                       22,                                  │
│                                       CONVERT(datetime,                    │
│                                               CONVERT(date,                │
│                                                       [残業開始日時]))))   │
│         ELSE                                                               │
│           0                                                                │
│       END AS [深夜残業分]                                                  │
│    FROM [表];                                                              │
└──────────────────────────────────────┘
分類:MSSQL
MSSQL/数値と文字の混在並び替え
2015年06月24日
[親]と[子]の二列(二階層)になっていて、それぞれ文字列型なのだが
場合によっては[子]が数値要素だけの場合、
数値としてソートをかけたいする(そうしないと「10」が「2」の前に来て格好悪い)

というこで、出し分けるSQL文は以下の通り
┌──────────────────────────────────────┐
│SELECT [主表].[親],                                                         │
│       [主表].[子],                                                         │
│    FROM [表] AS [主表]                                                     │
│    ORDER BY [主表].[親] ASC,                                               │
│             CASE                                                           │
│               WHEN EXISTS (                                                │
│                        SELECT *                                            │
│                            FROM [表] AS [調査表]                           │
│                            WHERE [調査表].[親] = [A].[親]                  │
│                              AND (ISNUMERIC([調査表].[子]) = 0             │
│                                OR ([調査表].[子] LIKE '0%'                 │
│                                AND [調査表].[子] <> '0'))                  │
│                    ) THEN                                                  │
│                 [主表].[子]                                                │
│               ELSE                                                         │
│                 FORMAT(CAST([主表].[子] AS int), '00000000')               │
│             END ASC;                                                       │
└──────────────────────────────────────┘
「0001」とかについては文字列として並び替えるおまけつき(しかも「0」だけは除く)
分類:MSSQL
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 次へ