2017-01-06 18 views
0

汎用テーブルがあるテーブルのレポートを実行しています。したがって、 "ParameterValue"フィールドの値にはさまざまな種類のデータが含まれます。私がしようとしているのは、「ParameterName」列が「Historian Timestamp」に等しい場合にのみ変換を実行することです。CTEを使用したTSQLステートメントの実行順序

これは、次のデータ

╔═══════════╦═══════════╦═══════════════╦══════════════════╦═══════════════════╦═══════════╦══════════╦═══════════════════════════╦═════════════════════╦════════════════════════════════════╗ 
║ LogbookId ║ CommentId ║ CommentTypeId ║  Comment  ║ CommentDetailTime ║ FirstName ║ LastName ║  ParameterValue  ║  Name   ║   HistorianTimestamp   ║ 
╠═══════════╬═══════════╬═══════════════╬══════════════════╬═══════════════════╬═══════════╬══════════╬═══════════════════════════╬═════════════════════╬════════════════════════════════════╣ 
║   1 ║   2 ║    1 ║ I entered 1  ║ 53:39.8   ║ Jason  ║ Turan ║ 2016-11-29T12:47:14  ║ Historian Timestamp ║ 2016-11-29 12:47:14.0000000 +00:00 ║ 
║   1 ║  54 ║    1 ║ Note on tablet. ║ 42:01.8   ║ Jason  ║ Turan ║ 2016-12-05T13:36:34  ║ Historian Timestamp ║ 2016-12-05 13:36:34.0000000 +00:00 ║ 
║   1 ║  55 ║    1 ║ testnotes  ║ 47:37.7   ║ Desiree ║ Teter ║ 2016-12-07T15:13:29  ║ Historian Timestamp ║ 2016-12-07 15:13:29.0000000 +00:00 ║ 
║   4 ║  56 ║    1 ║ notes   ║ 09:16.4   ║ Desiree ║ Teter ║ 2016-12-08T14:00:56  ║ Historian Timestamp ║ 2016-12-08 14:00:56.0000000 +00:00 ║ 
║   4 ║  56 ║    1 ║ notes 2   ║ 09:39.5   ║ Desiree ║ Teter ║ 2016-12-08T14:00:56  ║ Historian Timestamp ║ 2016-12-08 14:00:56.0000000 +00:00 ║ 
║   4 ║  57 ║    1 ║ ?    ║ 36:19.2   ║ Desiree ║ Teter ║ 2016-12-08T14:00:56  ║ Historian Timestamp ║ 2016-12-08 14:00:56.0000000 +00:00 ║ 
║   4 ║  59 ║    1 ║ testnotes sdfsdf ║ 29:42.1   ║ Desiree ║ Teter ║ 2016-12-08T14:00:56-06:00 ║ Historian Timestamp ║ 2016-12-08 14:00:56.0000000 -06:00 ║ 
╚═══════════╩═══════════╩═══════════════╩══════════════════╩═══════════════════╩═══════════╩══════════╩═══════════════════════════╩═════════════════════╩════════════════════════════════════╝ 

を返し、私が実行しているクエリ...

WITH LogbookSourceObjects AS (
    SELECT CAST(obj.NAME AS INT) as LogbookId, ObjectId 
    FROM PISourceObject obj 
    JOIN PISource s ON s.SourceID = obj.SourceId 
    WHERE s.Name ='DEDR' AND ISNUMERIC(obj.NAME) = 1 
), 
Comments AS (
    SELECT lso.LogbookId, 
      c.CommentId, 
      c.CommentTypeId, 
      cd.Comment, 
      cd.CommentDetailTime, 
      u.FirstName, 
      u.LastName, 
      cp.ParameterValue, 
      p.Name, 
      CONVERT(DATETIMEOFFSET, cp.ParameterValue) AS HistorianTimestamp 
    FROM LogbookSourceObjects lso 
    JOIN PIComment c ON c.ObjectId = lso.ObjectId 
    JOIN PICommentDetail cd ON cd.CommentId = c.CommentId 
    JOIN PICommentType ct ON ct.CommentTypeId = c.CommentTypeId 
    JOIN PICommentParameter cp on cp.CommentId = c.CommentId 
    JOIN PIParameter p on cp.ParameterId = p.ParameterId 
    JOIN PIUser u on u.UserId = cd.UserId 
    WHERE p.Name ='Historian Timestamp') 
SELECT * FROM COMMENTS 

があるしかし、私は、CTEコラム「HistorianTimestamp」にフィルタを追加するとき。次のエラーが表示されます。

メッセージレベル241、状態1、行1 文字列から日付および/または時刻を変換するときに変換に失敗しました。

おそらく、実行エンジンがwhere句の前にselect文を実行することを決定したためです。それは間違っていませんか?命令の実行順序を実行エンジンが尊重すべきではないか? IEはwhere節がselectの前に適用されます。ステートメントを書き直すにはどうしたらいいですか?

+1

これは、クエリを実行する順番を選択するオプティマイザです。この事件のより簡単な例については、[この質問](http://stackoverflow.com/questions/41109677/cte-returning-error)を参照してください。 – scsimon

+0

あなたは同様の質問をここで見ることができます。 http://stackoverflow.com/questions/41109677/cte-returning-error – DVT

+0

ヒント:適切なソフトウェア(MySQL、Oracle、DB2など)とバージョンの両方でデータベースの質問にタグを付けると便利です。 'sql-server-2014'です。構文と機能の相違は、しばしば答えに影響します。 – HABO

答えて

0

あなたが持っている時はいつでもまず、:

SELECT * FROM <someCTE> 

あなたはあまりにも多くのCTE私見を持っていることを意味し。

あなたは、このようなクエリを簡素化できます。

WITH LogbookSourceObjects AS (
    SELECT CAST(obj.NAME AS INT) as LogbookId, ObjectId 
    FROM PISourceObject obj 
    JOIN PISource s ON s.SourceID = obj.SourceId 
    WHERE s.Name ='DEDR' AND ISNUMERIC(obj.NAME) = 1 
) 
SELECT lso.LogbookId, 
     c.CommentId, 
     c.CommentTypeId, 
     cd.Comment, 
     cd.CommentDetailTime, 
     u.FirstName, 
     u.LastName, 
     cp.ParameterValue, 
     p.Name, 
     CONVERT(DATETIMEOFFSET, cp.ParameterValue) AS HistorianTimestamp 
FROM LogbookSourceObjects lso 
JOIN PIComment c ON c.ObjectId = lso.ObjectId 
JOIN PICommentDetail cd ON cd.CommentId = c.CommentId 
JOIN PICommentType ct ON ct.CommentTypeId = c.CommentTypeId 
JOIN PICommentParameter cp on cp.CommentId = c.CommentId 
JOIN PIParameter p on cp.ParameterId = p.ParameterId 
JOIN PIUser u on u.UserId = cd.UserId 
WHERE p.Name ='Historian Timestamp' 
AND CONVERT(DATETIMEOFFSET, cp.ParameterValue) > CONVERT(DATETIMEOFFSET, '2016-11-29T00:00:00-06:00') 
AND CONVERT(DATETIMEOFFSET, cp.ParameterValue) < CONVERT(DATETIMEOFFSET, '2016-11-30T00:00:00-06:00'); 

これはほぼ確実にまだ失敗しますが、簡単に少しのトラブルシューティングを行います。その後、(私の頭の上から)試みることができる:

AND ISDATE(CONVERT(DATETIMEOFFSET, cp.ParameterValue)) = 1 

それとも...

AND TRY_CONVERT(DATETIMEOFFSET, cp.ParameterValue) > CONVERT(DATETIMEOFFSET, '2016-11-29T00:00:00-06:00') 
AND TRY_CONVERT(DATETIMEOFFSET, cp.ParameterValue) < CONVERT(DATETIMEOFFSET, '2016-11-30T00:00:00-06:00'); 

思考のためだけいくつかの食品。