3

私は現在、2つの異なる日付間の日数の差を計算する必要があるクエリに取り組んでいます。私はDATE以前に列に問題がありました。なぜなら、それらはすべてnumeric列として保存されているため、完全に苦痛です。

昔と同じように使っCONVERTて、弦のさまざまな部分を作ってみましたDATETIMEが、運が悪かったです。

コメント行--convert(datetime,)は私が問題を抱えているところです。基本的には、使用可能な形式に変換する必要があるPO_DATEのでLINE_DOCK_DATE、2つの日数の差を計算できます。

USE BWDW

GO

SELECT 

  [ITEM_NO]
  ,[ITEM_DESC]
  ,[HEADER_DUE_DATE]
  ,[BWDW].[dbo].[DS_tblDimWhs].WHS_SHORT_NAME AS 'Warehouse'
  ,[BWDW].[dbo].[DS_tblFactPODtl].[PO_NO] AS 'PO NUMBER'
  ,[BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE] AS 'Start'
  ,[BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] AS 'Status'
  ,[BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] AS 'End'
  --,(SELECT CONVERT(DATETIME, CONVERT(CHAR(8), [BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE])) FROM dbo.DS_tblFactPODtl)


FROM [BWDW].[dbo].[DS_tblFactPODtl] 
INNER JOIN [BWDW].[dbo].[DS_tblDimWhs] ON [BWDW].[dbo].[DS_tblFactPODtl].WAREHOUSE = [BWDW].[dbo].[DS_tblDimWhs].WAREHOUSE
INNER JOIN [BWDW].[dbo].[DS_tblFactPO] ON [BWDW].[dbo].[DS_tblFactPODtl].PO_NO = [BWDW].    [dbo].[DS_tblFactPO].PO_NO
WHERE [BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] = 'Closed'
AND [BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] <> 0

以前に取り組んだプロジェクトから保存したスニペットがあり、今日から別の年までの結果のみを表示する必要がありました。そこにはたくさんのCASTとCONVERTSが含まれていましたが、同じ方法を試しましたが成功しませんでした。

長期的には、各データベーステーブルに列を追加してdatetime、将来使用できる適切な列を含めたいと思います...しかし、それは別の話です。NUMERICへの変換などについて説明しているstackoverflowに関する多数の投稿を読みましたが、NUMERICからに戻るものは何もありませんDATETIME

データ例:

Start    | End      | Difference
--------------------------------
20110501 | 20111019 | 171
20120109 | 20120116 | 7
20120404 | 20120911 | 160

差を計算しようとしているだけです。

アーロンごとに変更:

SELECT
  FPODtl.[ITEM_NO] AS [Item]
  ,FPODtl.[ITEM_DESC] AS [Description] 
  ,D.WHS_SHORT_NAME AS [Warehouse]
  ,FPODtl.[PO_NO] AS [PO NUMBER]
  ,FPODtl.[PO_DATE] AS [Start]
  ,FPODtl.[PO_STATUS] AS [Status]
  ,FPODtl.[LINE_DOCK_DATE] AS [End]
  ,DATEDIFF
  (
    DAY,
    CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
      THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
    CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
      THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
  )
    FROM [dbo].[DS_tblFactPODtl] AS FPODtl 
    INNER JOIN [dbo].[DS_tblDimWhs] AS D 
  ON FPODtl.WAREHOUSE = D.WAREHOUSE
    INNER JOIN [dbo].[DS_tblFactPO] AS FPO 
  ON FPODtl.PO_NO = FPO.PO_NO
    WHERE FPODtl.[PO_STATUS] = 'Closed'
    AND FPODtl.[LINE_DOCK_DATE] <> 0;
4

3 に答える 3

9
DECLARE @x NUMERIC(10,0);

SET @x = 20110501;

SELECT CONVERT(DATETIME, CONVERT(CHAR(8), @x));

結果:

2011-05-01 00:00:00.000

2 つを比較するには:

DECLARE @x NUMERIC(10,0), @y NUMERIC(10,0);

SELECT @x = 20110501, @y = 20111019;

SELECT DATEDIFF
(
  DAY, 
  CONVERT(DATETIME, CONVERT(CHAR(8), @x)),
  CONVERT(DATETIME, CONVERT(CHAR(8), @y))
);

結果:

171

さらに重要なことは、テーブルを修正することです。日付を数値として保存するのをやめます。それらを日付として保存します。この変換でエラーが発生する場合は、データの選択が不適切で、不適切なデータがテーブルに取り込まれたことが原因です。あなたはそれを回避することができます - 潜在的に - の古いバージョンを書くことによってTRY_CONVERT():

SELECT DATEDIFF
(
  DAY, 
  CASE WHEN ISDATE(col1)=1 THEN CONVERT(DATETIME, col1) END,
  CASE WHEN ISDATE(col2)=1 THEN CONVERT(DATETIME, col2) END
)
FROM 
( 
  SELECT 
    col1 = CONVERT(CHAR(8), col1), 
    col2 = CONVERT(CHAR(8), col2)
  FROM dbo.table
) AS x;

これにより、いずれかの列にガベージがある行に対して null が生成されます。元のクエリを次のように変更します。

SELECT
  [ITEM_NO] -- what table does this come from?
  ,[ITEM_DESC] -- what table does this come from?
  ,[HEADER_DUE_DATE] -- what table does this come from?
  ,D.WHS_SHORT_NAME AS [Warehouse] -- don't use single quotes for aliases!
  ,FPODtl.[PO_NO] AS [PO NUMBER]
  ,FPODtl.[PO_DATE] AS [Start]
  ,FPODtl.[PO_STATUS] AS [Status]
  ,FPODtl.[LINE_DOCK_DATE] AS [End]
  ,DATEDIFF
  (
    DAY,
    CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
      THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
    CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
      THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
  )
FROM [dbo].[DS_tblFactPODtl] AS FPODtl 
INNER JOIN [dbo].[DS_tblDimWhs] AS D 
  ON FPODtl.WAREHOUSE = D.WAREHOUSE
INNER JOIN [dbo].[DS_tblFactPO] AS FPO 
  ON FPODtl.PO_NO = FPO.PO_NO
WHERE FPODtl.[PO_STATUS] = 'Closed'
AND FPODtl.[LINE_DOCK_DATE] <> 0;
于 2013-02-26T22:13:04.413 に答える
2

数値として保存された日付が次のようになっている場合:20130226今日の場合、次のように変換する、DATEまたは次のDATETIMEようになります。

SELECT CONVERT(DATETIME,CONVERT(VARCHAR(8),NumberDate),112)
于 2013-02-26T21:50:33.020 に答える
0

パーツから日付を作成する簡単な式は次のとおりです。

DateAdd( Month, (( @Year - 1900 ) * 12 ) + @Month - 1, @Day - 1 )

@Year元のフィールドの部分文字列を使用して、@Monthとを抽出するだけ @Dayです。たとえば19531231、1953 年 12 月 31 日のような数値がある場合、次のように実行できます。

DateAdd( Month, (( SubString(Cast(DateField As Varchar(8)), 1, 4) - 1900 ) * 12 ) + 
                   SubString(Cast(DateField As Varchar(8)), 5, 2) - 1, 
                   SubString(Cast(DateField As Varchar(8)), 7, 2) - 1 )
于 2013-02-26T21:06:55.660 に答える