2009-11-26 5 views
4

SQL Server, en essayant d'obtenir le jour de la semaine via une fonction UDF déterministe.Fonction scalaire déterministe pour obtenir le jour de la semaine pour une date

Je suis sûr que cela doit être possible, mais je n'arrive pas à le comprendre.

MISE À JOUR: EXEMPLE DE CODE ..

CREATE VIEW V_Stuff WITH SCHEMABINDING AS 
SELECT  
MD.ID, 
MD.[DateTime] 
... 
     dbo.FN_DayNumeric_DateTime(MD.DateTime) AS [Day], 
     dbo.FN_TimeNumeric_DateTime(MD.DateTime) AS [Time], 
... 
FROM  {SOMEWHERE} 
GO 
CREATE UNIQUE CLUSTERED INDEX V_Stuff_Index ON V_Stuff (ID, [DateTime]) 
GO 
+0

S'il vous plaît montrer une partie de votre code, et comment vous avez l'intention de l'utiliser. –

Répondre

5

Ok, je me suis dit qu'il ..

CREATE FUNCTION [dbo].[FN_DayNumeric_DateTime] 
(@DT DateTime) 
RETURNS INT WITH SCHEMABINDING 
AS 
BEGIN 
DECLARE @Result int 
DECLARE @FIRST_DATE  DATETIME 
SELECT @FIRST_DATE = convert(DATETIME,-53690+((7+5)%7),112) 
SET @Result = datediff(dd,dateadd(dd,(datediff(dd,@FIRST_DATE,@DT)/7)*7,@FIRST_DATE), @DT) 
RETURN (@Result) 
END 
GO 
+0

Je viens de poster, vous devriez faire votre mise en œuvre :) +1 pour vous –

+1

http://stackoverflow.com/a/5109557/444382 est mieux – Brad

-1

Je ne sais pas ce que vous cherchez, mais si cela fait partie d'un site Web, essayez cette fonction php de http://php.net/manual/en/function.date.php

function weekday($fyear, $fmonth, $fday) //0 is monday 
{ 
    return (((mktime (0, 0, 0, $fmonth, $fday, $fyear) - mktime (0, 0, 0, 7, 17, 2006))/(60*60*24))+700000) % 7; 
} 
+0

Merci, mais je suis à la recherche d'une fonction scalaire SQL Server – Dve

0

Il y a un déjà fonction intégrée dans SQL pour le faire:

SELECT DATEPART(weekday, '2009-11-11') 

EDIT: Si vous avez vraiment besoin UDF déterministe:

CREATE FUNCTION DayOfWeek(@myDate DATETIME) 
RETURNS int 
AS 
BEGIN 
RETURN DATEPART(weekday, @myDate) 
END 
GO 
SELECT dbo.DayOfWeek('2009-11-11') 

EDIT à nouveau: c'est en fait mal, comme DATEPART(weekday) n'est pas déterministe.

MISE À JOUR: DATEPART(weekday) est non déterministe car elle repose sur DATEFIRST (source).
Vous pouvez le modifier avec SET DATEFIRST mais vous ne pouvez pas l'appeler dans une fonction stockée.

Je pense que l'étape suivante consiste à make your own implementation, en utilisant votre DATEFIRST préféré à l'intérieur (et non compte tenu du tout, en utilisant par exemple lundi comme le premier jour).

+0

DatePart est non déterministe, donc ce n'est pas possible – Dve

-1

Le jour de la semaine? Pourquoi n'utilisez-vous pas simplement DATEPART?

DATEPART(weekday, YEAR_DATE) 
+1

DatePart est non-déterministe, donc ce n'est pas possible – Dve

-1

tu ne peux pas le sélectionner avec quelque chose comme:

SELECT DATENAME(dw, GETDATE()); 
+0

Question d'obtenir le DayOfWeek pas le nom. – Bharat

0

La solution proposée a un problème - il retourne 0 pour Les samedis. En supposant que nous cherchons quelque chose compatible avec DATEPART(WEEKDAY) c'est un problème.

Rien qu'une simple instruction CASE ne résoudra, cependant.

5

Approche légèrement similaire à la solution mentionnée ci-dessus, mais juste une ligne qui pourrait être utilisée à l'intérieur d'une fonction ou en ligne pour une colonne calculée.

Hypothèses:

  1. Vous n'avez pas les dates avant 31/12/1899 (qui est un dimanche)
  2. Vous voulez imiter @@ datefirst = 7
  3. @dt est smalldatetime , datetime, date ou datetime2 type de données

Si vous souhaitez plutôt être différent, changer la date « 18991231 » à une date avec le jour de la semaine que vous souhaitez égale 1. Th fonction e convert() est essentiel pour faire fonctionner l'ensemble chose - casting ne fait pas l'affaire:

((datediff (jour, convertir (datetime, '18991231', 112), @dt)% 7) + 1)

+1

si vous restez à la date 1899-12-31, vous pouvez même passer la conversion '((datediff (jour, -1, @dt)% 7) + 1)' –

1

Taken de Deterministic scalar function to get week of year for a date

; 
with 
Dates(DateValue) as 
(
    select cast('2000-01-01' as date) 
    union all 
    select dateadd(day, 1, DateValue) from Dates where DateValue < '2050-01-01' 
) 
select 
    year(DateValue) * 10000 + month(DateValue) * 100 + day(DateValue) as DateKey, DateValue,   
    datediff(day, dateadd(week, datediff(week, 0, DateValue), 0), DateValue) + 2 as DayOfWeek, 
    datediff(week, dateadd(month, datediff(month, 0, DateValue), 0), DateValue) + 1 as WeekOfMonth, 
    datediff(week, dateadd(year, datediff(year, 0, DateValue), 0), DateValue) + 1 as WeekOfYear 
    from Dates option (maxrecursion 0) 
1

Je sais que ce poste est une façon super vieux, mais je voulais faire quelque chose de semblable et est venu avec une autre solution et figurés Je posterais pour la postérité. De plus j'ai fait quelques recherches et n'ai pas trouvé beaucoup de contenu sur cette question.

Dans mon cas, j'essayais d'utiliser une colonne calculée PERSISTED, ce qui nécessite que le calcul soit déterministe. Le calcul j'est:

datediff(dd,'2010-01-03',[DateColumn]) % 7 + 1 

L'idée est de trouver un dimanche connu que vous savez avoir lieu avant toute date possible dans votre table (dans ce cas 3 Jan 2010), puis calculer le modulo 7 + 1 du nombre de jours depuis ce dimanche.

Le problème est que l'inclusion d'une date littérale dans l'appel de la fonction est suffisante pour la marquer comme non déterministe. Vous pouvez contourner cela en utilisant l'entier 0 pour représenter l'époque, qui pour SQL Server est le 1er janvier 1900, un dimanche.

datediff(dd,0,[DateColumn]) % 7 + 1 

Le +1 est tout simplement le résultat fonctionnent comme datepart (dw, [datecolumn]) lorsque datefirst est réglé sur 7 (par défaut aux USA), qui fixe dimanche à 1, lundi à 2, etc

Je peux aussi l'utiliser en conjonction avec case [thatComputedColumn] quand 1 puis 'dimanche' quand 2 puis 'lundi' ... etc. Wordier, mais déterministe, ce qui était une exigence dans mes environs.

+0

c'était une idée intéressante, mais ne fonctionne pas. dans mes tests, j'ai dû faire de votre '0' un' 4'. Je suppose que cela a à voir avec le premier jour de cette année, qui était un mercredi. Je ne sais pas comment cela a fonctionné en 2013 quand vous l'avez écrit parce que cette année a commencé un mardi. Les comptes de réponse de @ scottE pour ce http: // stackoverflow.com/a/5109557/444382 – Brad

+0

selon la définition de déterministe (http://msdn.microsoft.com/en-us/library/ms178091.aspx) cette solution est déterministe. La raison pour laquelle vous avez probablement obtenu un résultat différent a été votre paramètre de base de données firstdate (http://msdn.microsoft.com/en-us/library/ms178091.aspx). Vous ne pouvez pas faire persister une colonne calculée si elle n'est pas déterministe, et ce calcul peut être conservé –

+0

(je suppose que je ne comprends pas ce que vous entendez par "ne fonctionne pas") –

Questions connexes