Domanda

Ho una tabella di date chiamare [BadDates], ma ha solo una colonna in cui ogni record è una data da escludere. Ho un UDF come segue:

CREATE FUNCTION [dbo].[udf_GetDateInBusinessDays]
(
  @StartDate datetime,  --Start Date
  @NumberDays int           --Good days ahead
)
RETURNS datetime
AS
BEGIN
-- Declare the return variable here
DECLARE @ReturnDate datetime
SET @ReturnDate = @StartDate
DECLARE @Counter int
SET @Counter = 0
WHILE   @Counter < @NumberDays
BEGIN
    SET @ReturnDate = DateAdd(d,1,@ReturnDate)
    IF ((SELECT COUNT(ID)
        FROM dbo.[BadDates]
        WHERE StartDate = @ReturnDate) = 0)
    BEGIN
        SET @Counter = @Counter + 1
    END
END
RETURN @ReturnDate
END

Questa UDF funziona alla grande, ma è lento nella lavorazione. La stored procedure che utilizza questo corre l'UDF in ogni record. C'è altri modi per fornire la stessa funzionalità in un metodo più veloce.

Ogni aiuto è molto apprezzato!

È stato utile?

Soluzione

Non ho ancora testato questo, ma in teoria dovrebbe funzionare. Aggiungo il numero di giorni. Poi controllo se ci fossero baddates in tale intervallo. Se ci fossero aggiungo il numero di giorni cattivi e verificare se ci fossero più baddates nel range Ho appena aggiunto. Ripetere fino a quando non date cattivi.

CREATE FUNCTION [dbo].[udf_GetDateInBusinessDays]
(
  @StartDate datetime,  --Start Date
  @NumberDays int           --Good days ahead
)
RETURNS datetime
AS
BEGIN
-- Declare the return variable here
DECLARE @ReturnDate datetime
SET @ReturnDate = dateadd(d, @NumberDays, @StartDate);


DECLARE @d int;
SET @d = (select count(1) from baddates where startdate >= @StartDate and startdate <= @ReturnDate);

declare @t datetime;

WHILE   @d > 0
BEGIN
    set @t = @ReturnDate;
    set @ReturnDate = dateadd(d, @d, @ReturnDate);
    SET @d = (select count(1) from baddates where startdate > @t and startdate <= @ReturnDate);
END

RETURN @ReturnDate
END

Altri suggerimenti

Sto assumendo che ciò che si sta cercando di fare è calcolare la data che è x giorni lavorativi passato un dato date.e.g. quale data è di 10 giorni lavorativi a partire da oggi. Sono anche supponendo che la tabella contiene baddates giorni non lavorativi per esempio Fine settimana e nei giorni festivi.

Ho incontrato requisiti simili in passato e di solito finito con tavolo da giorni che contiene tutte le date possibili con un flag che indica se una data particolare, è una giornata di lavoro o meno.

Ho quindi utilizzare quella tabella per calcolare quale data è x giorni lavorativi dalla data prevista selezionando il record che è x giorni dopo la data di inizio.

Quindi, qualcosa di simile

 CREATE TABLE all_days (  
  dated DATETIME,  
  day_state CHAR(1)  
  )

Dove day_state è il valore di
  D - Giorno Lavorativo
  W - Weekend
  B - Bank Holiday

L'SQL per trovare la data dopo x giorni lavorativi diventa allora

SELECT MAX(dated)
FROM (
  SELECT TOP(@number_days) dated
  FROM all_days
  WHERE day_state = 'D'
  AND dated >= @start_date
  ORDER by dated ASC
)

Questo codice non è testato, ma dovrebbe darvi l'idea generale. Non si può decidere di differenziare tra i fine settimana ei giorni festivi, nel qual caso si potrebbe rinominare il day_state a working_day e ne fanno un campo di bit.

Si dovrebbe creare un indice univoco composito datato e day_state.

Si consiglia di mettere un indice su BadDates.StartDate, ma ci possono essere altre soluzioni, migliori.

Ok perché stai contando quando è possibile utilizzare la parola chiave esista? Se la sua perché si può avere date multiple dello stesso tipo in Badates questo sembra sbagliato. COUNT sarà probabilmente alla ricerca attraverso l'intera tabella di contare i casi di startdate quando tutto ciò che serve è 1 da escludere.

Hai avuto uno sguardo al piano di query per vedere cosa sta succedendo?

Sembra che si sta utilizzando questo UDF per calcolare la differenza tra due date. Se sto interpretando correttamente questo allora vi consiglio di utilizzare il built-in funzione di DateDiff.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top