質問

以下のクエリを、より読みやすく、変更可能なものにリファクタリングしたいと考えています。前半は、クエリ元のデータベースを除き、後半と同じです (ただし、テーブル名は同じです)。

  SELECT
    Column 1 AS c1,
    ...
    Column N AS cN
  FROM
    database1.dbo.Table1

UNION

  SELECT
    'Some String' as c1,
    ...
    NULL as cN
  FROM
    database1.dbo.Table2

UNION

  SELECT
    Column 1 AS c1,
    ...
    Column N AS cN
  FROM
    database2.dbo.Table1

UNION

  SELECT
    'Some String' as c1,
    ...
    NULL as cN
  FROM
    database2.dbo.Table2

このクエリは次の定義です。 ドライ 書き直してほしいと呼びかけているのですが、その方法がわかりません。

編集:linq は使用できないので、明確な結果が必要です。返される結果ではなく、物理ファイルのサイズを小さくするためにクエリを検討しています。

編集:私がクエリを実行しているデータベースは、独自の ERP データベースです。それを再構築するという選択肢はありません。

役に立ちましたか?

解決

これはかなり標準のSQLパターンです。時にはそれがinadvisedly SQLにDRYのようなOOP /手続きのコードの原則を転送するのは簡単ですが、彼らは必ずしも譲渡概念ではありません。

あなたは対サブモジュールを介したハンティング、クエリの全体の論理設計を完全に理解することができますどのように簡単に注意してください。部分式の一つは余分な列、または列を逆に持っていた場合、それが飛び出します。これは、基本的にはそれを混乱う解砕実行ユニットとして完全に理解するために非常に単純なSQL文です。

そして、あなたがデバッグしているとき、それは選択文の一部行使するエディタのテキストの強調表示オプションを使用できるのは便利です - 手続き型コードには存在しない技術を。彼らものCTEは、この不便を作ることができるなどのビューに散乱している場合OTOH、それはすべての部分を下に追跡しようとしている厄介な取得することができます。

他のヒント

私はここで思い切って言いますが、あなたが私たちにくれた情報に基づいて、こう言います。

それはそれでいいことだ

私はあなたが意図的に個別のレコードを使用する場合に限りUNION ALLの代わりにUNIONを使用しているバット見送り一つパフォーマンスのヒント。シンプルUNIONは時間がかかり、重複を排除します。 UNION ALLはそれをしません。

あなたは、動的SQLおよびループでそれを書き換えることができますが、私は結果が悪いことだと思います。動的SQLアプローチを正当化するのに十分な重複したコードがある場合、私はそれが正当化されることができると思います。

また、あなたは、LINQのようなものの中に、ストアドプロシージャの外にロジックを移動すると考えられてきましたか?多くの人にとって、これは私がちょうど求めているので、オプションではありません。

最後の注意:ちょうどそれがきれいに見えるように壊れていないものを修正するために衝動に抵抗します。クリーンアップがメンテナンス等、検証、中補佐官は、それのために行くなります。

問題は何ですか?長すぎる?あまりにも繰り返し?

は、時々、あなたは醜いSQLを取得する - ずっとあなたがそれについて行うことができません。

私はそれらを一緒に使用すると、別のビューを使用する場合を除き、それをクリーンアップする方法を参照して、労働組合はありません。

私はほぼ十分なゼロオーバーヘッド課すビュー、に投票(OK、多分小さなコンパイル時のコストをそれがすべてであるべき)。次に、あなたのprocsのは、フォームのようなものになる。

SELECT * FROM database1.view1
UNION
SELECT * FROM database1.view2
UNION
SELECT * FROM database2.view1
UNION
SELECT * FROM database2.view2

私は、私はほとんどのプラットフォームがそれを容認期待するが、私は、それ以上、それを凝縮したいと思いますかはわからない。

動的SQLをテーマに - ここのサンプルである - それはどんな優れているかどうかわかりません。利点は、あなたが一度だけSELECTリストを記述する必要があります。

DECLARE @Select1 varchar(1000)
DECLARE @Select2 varchar(1000)

DECLARE @SQL varchar(4000)


SET @Select1 = 'SELECT
    Column 1 AS c1,
    ...
    Column N AS cN'


SET @Select2 = 'SELECT
    ''Some String'' as c1,
    ...
    NULL as cN'


SET @SQL = @Select1 + ' FROM database1.dbo.Table1 '

SET @SQL = @SQL + ' UNION ' + @Select2 + ' FROM database1.dbo.Table2 '

SET @SQL = @SQL + ' UNION ' + @Select1 + ' FROM database2.dbo.Table1 '

SET @SQL = @SQL + ' UNION ' + @Select2 + ' FROM database2.dbo.Table2 '


EXEC @SQL
すべてのprocsのは次のようになり場合は

- あなたはおそらく建築の問題を持っている。

表2に、すべての呼び出しはただ一つの有用なフィールドを持っていますか? (ユニオンのため、ただ一つの行を有する終わる?)

私は全く秒でもINFORMATION_SCHEMAを使用して動的に列リストを生成するために、これまでのように起こって、このジョブのパラメータ化、動的SQLおよび/またはコード生成と一緒に行くのアイデア。これは、何が必要正確ではありませんが、それは(あなたがデータベースとテーブルのテーブルをオフに発生する可能性がある)スタートだ。

DECLARE @template AS varchar(MAX)
SET @template = 'SELECT {@column_list} FROM {@database_name}.dbo.{@table_name}'
DECLARE @column_list AS varchar(MAX)

SELECT @column_list = COALESCE(@column_list + ',', '') + COLUMN_NAME
FROM database1.dbo.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table_name
ORDER BY ORDINAL_POSITION

DECLARE @sql AS varchar(MAX)
SET @sql = @template
SET @sql = REPLACE(@sql, '{@column_list}', @column_list)
SET @sql = REPLACE(@sql, '{@database_name}', @database_name)
SET @sql = REPLACE(@sql, '{@table_name}', @table_name)

行の数に応じて、あなたが最良のその周りにSELECT DISTINCTクエリを選択する上で、UNION ALLを使用している可能性があり、返されました。 私は前に同様の問題を見て2つの異なるスタイルのためのさまざまな実行計画を持っていた。

SELECT DISTINCT subquery.c1, subquery.cN
FROM
(
SELECT Column 1 AS c1, Column N AS cN FROM database1.dbo.Table1
UNION ALL
SELECT 'Some String' as c1, NULL as cN FROM database1.dbo.Table2
UNION ALL
SELECT Column 1 AS c1, Column N AS cN FROM database2.dbo.Table1
UNION ALL
SELECT 'Some String' as c1, NULL as cN FROM database2.dbo.Table2
) subquery
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top