2

私はそのようなテーブルの例を持っています:

State   Project Build Type  ACTUAL0     ACTUAL1     ACTUAL2  
------- ------- ----------- ----------- ----------- ----------
Ohio    154214  Residential 1/5/2013    2/25/2013   7/12/12  
Utah    214356  Commercial  7/08/13     6/9/13      7/1/12

実際の単語で始まる列ヘッダーを取得し、特定の日付よりも小さい日付の数を取得するレポートを作成しようとしています。実際の単語で始まる列ヘッダーを作成する一時テーブルがあります。これは単なる例であり、実際には 250 を超える列名があります。したがって、テーブルは次のようになります。

MilestoneNmbr  
-------------
ACTUAL1  
ACTUAL2  
ACTUAL3  

今私がうまくいくと思うのは、行を列ヘッダーの変数として取り、日付を関数に渡すことです。ここに私が作成した関数があります:

CREATE FUNCTION [dbo].[GetMSActualCount] 
(
    @ACTUAL nvarchar(16),
    @DATE nvarchar(16)
)
RETURNS int
AS
BEGIN
DECLARE @ACTUALRETURN int
    DECLARE @SQL nVarchar(255) = 
    'SELECT COUNT(' + @ACTUAL + ') AS Expr1
    FROM [CASPR_MILESTONES_000-036]
    WHERE '+ @ACTUAL +' > ' + @DATE
exec sp_executesql @SQL, N''
SET @ACTUALRETURN = @SQL
    -- Return the result of the function
    RETURN @ACTUALRETURN

END

次のクエリを実行すると:

DECLARE @DATE varchar(20)
SET @DATE = '''1/1/2013'''
SELECT MilestoneNmbr, dbo.getMSActualCount(milestonenmbr,@Date) from #List_CASPR_Milestones

したがって、私のエラーは、関数で動的 SQL を使用できないことです。ということで、どうしたらよいでしょうか?ここでの私の簡単なクエリは、数百行になると思います。これを行う別の簡単な方法はありますか?

編集:

私が探している結果は次のようなものです。

MilestoneNmbr   CountofDate  
--------------- ------------
ACTUAL1         200  
ACTUAL2         344  
ACTUAL3         400  
4

3 に答える 3

2

私はチャールズに100%同意します。構造を変更できる場合、これは私がすることです:

可能であれば、ビルド タイプ テーブル (ID/ビルド タイプ) を用意し、何かのテキストとして必要でない限り、テキスト列は使用しないでください。コード化できるものはすべてコード化します。

2 つのテーブル:

  • プロジェクト ヘッダー (Proj_ID (long_int)/State (int または char(2)) / build_type (int))、プライマリ キー Proj_id 自体、または一意でない場合は新しい ID (PK Proj_id & State はあまり役に立たないため) PKとして)。
  • Project_date (Proj_ID (上記の PK と同じ) / Date_ID (int) / Actual_Date (DateTime))

したがって、2番目の例は次のようになります。

Project_Header:

214356 / UT / 2  (being 1 Residential, 2 Commercial, 3 Industrial ...)

プロジェクトの日付:

 214356 / 0 / '07/08/13'
 214356 / 1 / '06/09/13'
 214356 / 2 / '07/01/12'

プロジェクトごとの最新のビルド日は次のとおりです。

Select 'Actual_date' 
from Project_date 
where Project_id='nnn' 
order by date_id DESC 
Limit 1;

クエリは次のようになります (日付が増分順の場合):

Select Project_id, max(Date_id)
From Project_date
Group by Project_id
having Actual_date < @date

あなたはそれがかなり簡単であることがわかります。

構造を変更できないが、新しいテーブルを作成できる場合は、その醜いテーブルを取得して Project_Date を 1 日に x 回生成する SP を作成します (または、最初のテーブルの inert/update のトリガーに関連付けることもできます)。 ) と Project_header を 1 日に 1 回 (必要に応じてさらに頻繁に)。これは、試行しているよりも時間と労力が大幅に少なくて済み、さらに他のクエリにも使用できます。

于 2013-09-05T23:13:39.033 に答える
0

これを解決するために、実際の日付を格納するテーブルを作成しました。次に、List_ACTUAL テーブルの各行をループして名前を取得し、渡した変数よりも大きい日付名の数を選択します。これを PROC に変換します。こうやって:

DECLARE @MS nvarchar(16)
DECLARE MSLIST CURSOR LOCAL FOR SELECT MilstoneNmbr FROM List_ACTUAL
DECLARE @SQL nvarchar(max)
DECLARE @DATE nvarchar(16)
SET @DATE = '1/1/2013'
CREATE #TEMP (Milestones nvarchar(16), Frozen int)
OPEN MSLIST
FETCH NEXT FROM MSLIST INTO @MS
WHILE @@FETCH_STATUS=0
BEGIN
SELECT @SQL = 'INSERT INTO #TEMP VALUES (''' +@MS+ ''', (Select count(' +@MS+ ') FROM PROJECTDATA WHERE ' +@MS+ ' > ''' + @Date + '''))'
EXEC sp_executesql @SQL, N''
FETCH NEXT FROM MSLIST INTO @MS
END
CLOSE MSLIST
DEALLOCATE MSLIST  

これが誰かに役立つことを願っています。

于 2013-09-06T22:33:39.410 に答える