none
SQL und Index... RRS feed

  • Frage

  • Hallo,

    ich muss ein Datumsformat abspeichern ohne den Typ Date zu verwenden.

    Es wird abgelegt in ein Char(10) Feld...

    Um folgende Abfrage zu beschleunigen habe ich einfach einen Index auf dieses Feld
    gelegt...


    select blabla from blabla where (day(anlageam) >= '05' and MONTH(anlageam) >= '01' and YEAR(anlageam) >= '2011' ) AND
    (day(anlageam) <= '17' and MONTH(anlageam) <= '01' and YEAR(anlageam) <= '2011' )

    Da ich extrem mit dem Ausführungsplan auf Kriegsfuss stehe und diesen bis heute nicht wirklich verstehe,
    einfach mal eine direkte Frage :

    Reicht dieser Index aus ?

    Create index AnlangeAM on blabla ( AnlageAM )

    oder geht sowas auch :

    Create index AnlangeAM1 on blabla ( Day(AnlageAM) )
    Create index AnlangeAM2 on blabla ( Month(AnlageAM) )
    Create index AnlangeAM3 on blabla ( Year(AnlageAM) )

    oder muss ich neben dem Feld Anlage noch 3 weitere Felder speichenr um die 3
    Informationen zusätzlich noch zu haben und dann jeweils einen Index auf das Feld ?

    Danke euch,

    Mario

    Freitag, 18. Februar 2011 11:26

Antworten

  • hi Mario,

    > ich muss ein Datumsformat abspeichern ohne den Typ Date zu verwenden.
    Warum?

    Deine DAY(), MONTH() und YEAR() Funktionen müssen dann dein CHAR(10) implizt convertieren.

    > Create index AnlangeAM1 on blabla ( Day(AnlageAM) )
    Das geht nicht. Du kannst allerdings einen Index auf berechnete Spalten - CONVERT(DATE, [AngelegtAm], 101) bzw. das entsprechende Format - legen.

    http://msdn.microsoft.com/de-de/library/ms186241.aspx
    http://msdn.microsoft.com/de-de/library/ms187928.aspx
    http://msdn.microsoft.com/de-de/library/ms187928.aspx

     

    CREATE TABLE #test
     (
      ID INT ,
      cdate CHAR(10) ,
      ddate AS CONVERT(DATE, cdate, 101)
     ) ;
    
    CREATE INDEX ix_test_1 ON #test (ddate) ;
    
    INSERT INTO #test
      ( id, cdate )
    VALUES ( 1, '12/31/1900' ) ;
    
    SELECT *
    FROM #test ;
    
    DROP TABLE #test ;
    

     

     


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Freitag, 18. Februar 2011 11:43
    Moderator
  • Warum machst Du es Dir so kompliziert? Warum verwendest Du nicht einen der für Datumswerte vorgesehenen Datentypen? Sofern es nicht einen wirklich guten Grund gibt, warum das als char(10) gespeichert werden muss, sollte Du diese Idee schnellstens verwerfen.

    Stefan hat ja bereits die Idee der Indizes auf berechnete Spalte eingebracht. Wenn Du diesen Datumsstring vorher zusammensetzt und in die Abfrage einbaust so etwa wie

    DECLARE @DatumVon char(10);
    DECLARE @DatumBis char(10);

    SELECT @DatumVon = < hier die einzelnen Werte zusammensetzen ...> -- das gleiche für @DatumBis

    select blabla from blabla where anlageam >= @DatumVon AND anlageam <= @DatumBis

    könnte auch ein Index nur auf AnlageAM wieder Sinn machen.


    -- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org
    Freitag, 18. Februar 2011 12:26
  • Hallo,

    ich muss ein Datumsformat abspeichern ohne den Typ Date zu verwenden.

    Es wird abgelegt in ein Char(10) Feld...

    -- Hallo Mario,
    --
    -- Nehmen wir an,
    -- dass der Datentype Date und Date/Convert-Funktionen nicht verwendet werden dürfen
    -- und das Datum als char(10) gespeichert werden muss.
    use tempdb
    go
    -- Testtabelle
    create table Blabla
    (
    	 BlablaID		int identity primary key not null
    	,AnlageAm		char(10) not null
    	,AnlageAmIndex	int not null
    )
    go
    
    -- Index mit eingeschlossenen Spalten
    -- http://msdn.microsoft.com/de-de/library/ms190806.aspx
    create nonclustered index IX_Blabla_AnlageAmIndex_inc_AnlageAm_BlablaID
    on Blabla(AnlageAmIndex asc)
    include(AnlageAm,BlablaID)
    go
    
    -- liefert dd-mm-yyyy als char(10) zurück
    create function dbo.GetDmyAsChar10
    (
    	 @day			int
    	,@month			int
    	,@year			int
    	,@delimiter		char(1)
    )
    returns char(10)
    begin
    	return
    		 right(cast(100+@day as char(3)),2) + @delimiter
    		+ right(cast(100+@month as char(3)),2) + @delimiter
    		+ cast(@year as char(4))
    end
    go
    
    -- liefert yyyymmdd als int zurück
    create function dbo.GetYmdAsInt
    (
    	 @day			int
    	,@month			int
    	,@year			int
    )
    returns int
    begin
    	return @year * 10000 + @month * 100 + @day
    end
    go
    
    -- die SP persistiert Daten in der Tabelle Blabla und liefer ID zurück
    create proc InsertIntoBlabla
    (
    	 @blablaID		int out
    	,@anlageAmJahr		int
    	,@anlageAmMohnat	int
    	,@anlageAmTag		int
    )
    as
    begin
    	declare @delimiter		char(1)
    	declare @anlageAm		char(10)
    	declare @anlageAmIndex		int
    set @delimiter = '-' set @anlageAm = dbo.GetDmyAsChar10(@anlageAmTag,@anlageAmMohnat,@anlageAmJahr,@delimiter) set @anlageAmIndex = dbo.GetYmdAsInt(@anlageAmTag,@anlageAmMohnat,@anlageAmJahr) insert into Blabla (AnlageAm,AnlageAmIndex) values(@anlageAm,@anlageAmIndex) set @blablaID = scope_identity() end go -- Testaufruf der Prozedur InsertIntoBlabla declare @blablaID int exec InsertIntoBlabla @blablaID out,@anlageAmJahr=2011,@anlageAmMohnat=2,@anlageAmTag=19 -- ID select @blablaID as [Blabla.BlablaID] go -- persistierte Daten select * from Blabla -- Abfrage, die BETWEEN (Transact-SQL) verwendet -- http://msdn.microsoft.com/de-de/library/ms187922.aspx select BlablaID, AnlageAm from Blabla where AnlageAmIndex between dbo.GetYmdAsInt(1,1,2011) and dbo.GetYmdAsInt(1,1,2012) go -- drops drop proc InsertIntoBlabla go drop function GetDmyAsChar10, GetYmdAsInt go drop table Blabla go -- hth

    Samstag, 19. Februar 2011 12:06

Alle Antworten

  • hi Mario,

    > ich muss ein Datumsformat abspeichern ohne den Typ Date zu verwenden.
    Warum?

    Deine DAY(), MONTH() und YEAR() Funktionen müssen dann dein CHAR(10) implizt convertieren.

    > Create index AnlangeAM1 on blabla ( Day(AnlageAM) )
    Das geht nicht. Du kannst allerdings einen Index auf berechnete Spalten - CONVERT(DATE, [AngelegtAm], 101) bzw. das entsprechende Format - legen.

    http://msdn.microsoft.com/de-de/library/ms186241.aspx
    http://msdn.microsoft.com/de-de/library/ms187928.aspx
    http://msdn.microsoft.com/de-de/library/ms187928.aspx

     

    CREATE TABLE #test
     (
      ID INT ,
      cdate CHAR(10) ,
      ddate AS CONVERT(DATE, cdate, 101)
     ) ;
    
    CREATE INDEX ix_test_1 ON #test (ddate) ;
    
    INSERT INTO #test
      ( id, cdate )
    VALUES ( 1, '12/31/1900' ) ;
    
    SELECT *
    FROM #test ;
    
    DROP TABLE #test ;
    

     

     


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    Freitag, 18. Februar 2011 11:43
    Moderator
  • Warum machst Du es Dir so kompliziert? Warum verwendest Du nicht einen der für Datumswerte vorgesehenen Datentypen? Sofern es nicht einen wirklich guten Grund gibt, warum das als char(10) gespeichert werden muss, sollte Du diese Idee schnellstens verwerfen.

    Stefan hat ja bereits die Idee der Indizes auf berechnete Spalte eingebracht. Wenn Du diesen Datumsstring vorher zusammensetzt und in die Abfrage einbaust so etwa wie

    DECLARE @DatumVon char(10);
    DECLARE @DatumBis char(10);

    SELECT @DatumVon = < hier die einzelnen Werte zusammensetzen ...> -- das gleiche für @DatumBis

    select blabla from blabla where anlageam >= @DatumVon AND anlageam <= @DatumBis

    könnte auch ein Index nur auf AnlageAM wieder Sinn machen.


    -- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org
    Freitag, 18. Februar 2011 12:26
  • Hallo,

    ich muss ein Datumsformat abspeichern ohne den Typ Date zu verwenden.

    Es wird abgelegt in ein Char(10) Feld...

    -- Hallo Mario,
    --
    -- Nehmen wir an,
    -- dass der Datentype Date und Date/Convert-Funktionen nicht verwendet werden dürfen
    -- und das Datum als char(10) gespeichert werden muss.
    use tempdb
    go
    -- Testtabelle
    create table Blabla
    (
    	 BlablaID		int identity primary key not null
    	,AnlageAm		char(10) not null
    	,AnlageAmIndex	int not null
    )
    go
    
    -- Index mit eingeschlossenen Spalten
    -- http://msdn.microsoft.com/de-de/library/ms190806.aspx
    create nonclustered index IX_Blabla_AnlageAmIndex_inc_AnlageAm_BlablaID
    on Blabla(AnlageAmIndex asc)
    include(AnlageAm,BlablaID)
    go
    
    -- liefert dd-mm-yyyy als char(10) zurück
    create function dbo.GetDmyAsChar10
    (
    	 @day			int
    	,@month			int
    	,@year			int
    	,@delimiter		char(1)
    )
    returns char(10)
    begin
    	return
    		 right(cast(100+@day as char(3)),2) + @delimiter
    		+ right(cast(100+@month as char(3)),2) + @delimiter
    		+ cast(@year as char(4))
    end
    go
    
    -- liefert yyyymmdd als int zurück
    create function dbo.GetYmdAsInt
    (
    	 @day			int
    	,@month			int
    	,@year			int
    )
    returns int
    begin
    	return @year * 10000 + @month * 100 + @day
    end
    go
    
    -- die SP persistiert Daten in der Tabelle Blabla und liefer ID zurück
    create proc InsertIntoBlabla
    (
    	 @blablaID		int out
    	,@anlageAmJahr		int
    	,@anlageAmMohnat	int
    	,@anlageAmTag		int
    )
    as
    begin
    	declare @delimiter		char(1)
    	declare @anlageAm		char(10)
    	declare @anlageAmIndex		int
    set @delimiter = '-' set @anlageAm = dbo.GetDmyAsChar10(@anlageAmTag,@anlageAmMohnat,@anlageAmJahr,@delimiter) set @anlageAmIndex = dbo.GetYmdAsInt(@anlageAmTag,@anlageAmMohnat,@anlageAmJahr) insert into Blabla (AnlageAm,AnlageAmIndex) values(@anlageAm,@anlageAmIndex) set @blablaID = scope_identity() end go -- Testaufruf der Prozedur InsertIntoBlabla declare @blablaID int exec InsertIntoBlabla @blablaID out,@anlageAmJahr=2011,@anlageAmMohnat=2,@anlageAmTag=19 -- ID select @blablaID as [Blabla.BlablaID] go -- persistierte Daten select * from Blabla -- Abfrage, die BETWEEN (Transact-SQL) verwendet -- http://msdn.microsoft.com/de-de/library/ms187922.aspx select BlablaID, AnlageAm from Blabla where AnlageAmIndex between dbo.GetYmdAsInt(1,1,2011) and dbo.GetYmdAsInt(1,1,2012) go -- drops drop proc InsertIntoBlabla go drop function GetDmyAsChar10, GetYmdAsInt go drop table Blabla go -- hth

    Samstag, 19. Februar 2011 12:06