Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL: Jahresanteile des Vertags berechnen? (https://www.delphipraxis.net/175266-sql-jahresanteile-des-vertags-berechnen.html)

romber 10. Jun 2013 12:45

Datenbank: SQL Server • Version: 2012 • Zugriff über: ADO

SQL: Jahresanteile des Vertags berechnen?
 
Hallo!

Ich habe eine Testtabelle, in der über 100.000 Verträge gespeichert sind. Jeder Vertrag hat unter anderem "Anfangsdatum", "Vertragsdauer" (in Monaten, mögliche Werte sind 1, 3, 6 und 12) und "Bezahlter Betrag". Ich möchte ich z. B. wissen, welcher Betrag aus allen Verträgen auf das Jahr 2012 anfällt. Das lässt sich errechnen, indem ich

1. Den Monatsanteil des Preises aus Vertragsdauer und Preis ermittle
2. Die Zahl der Vertragsmonate im Jahr 2012 aus Anfangsdatum und Vertragsdauer errechne
3. 1 mit 2 multipliziere

Nun muss ich dafür eine SQL-Abfrage erstellen. Mangels tiefgreifender SQL-Kenntnisse liste ich testweise alle Vertäge auf und führe für jeden Vertrag die o.g. Schritte aus. Nach zwei Raucherpausen kommt der Euro-Betrag raus :cheers:
:oops::oops::oops:

Das muss doch alles mit einer einzelnen Abfrage gehen. Kann mir jemand mit einem passenden Beispiel helfen?
Vielen Dank!

jobo 10. Jun 2013 13:30

AW: SQL: Jahresanteile des Vertags berechnen?
 
Deine Angaben sind noch etwas mager, also erstmal so bspw.
Code:
select Preis/LaufzeitInMonaten*MonateIn2012 from Vertrag
 where MonateIn2012>0
Hilfreich wäre z.B. die Angabe der Feldtypen (echte Datumstypen?) und des RDBMS. Gerade bei Datumsberechnungen gibt es viele herstellerspezifischen Funktionen.
Vermutlich bezieht sich die Aufgabenstellung auch nicht nur auf das Jahr 2012?

DeddyH 10. Jun 2013 13:31

AW: SQL: Jahresanteile des Vertags berechnen?
 
MS SQL 2012 ist doch angegeben.

romber 10. Jun 2013 13:34

AW: SQL: Jahresanteile des Vertags berechnen?
 
Vielen Dank für die schnelle Reaktion!

Zitat:

Zitat von jobo (Beitrag 1218027)
Hilfreich wäre z.B. die Angabe der Feldtypen (echte Datumstypen?) und des RDBMS. Gerade bei Datumsberechnungen gibt es viele herstellerspezifischen Funktionen.

Ich benutze SQL Server 2012. Die Datumsfelder sind vom Typ "smalldatetime".

Zitat:

Zitat von jobo (Beitrag 1218027)
Vermutlich bezieht sich die Aufgabenstellung auch nicht nur auf das Jahr 2012?

Genau. Das Jahr bzw. mehrere Jahre gibt man dynamisch an. Die Abfrage soll die Summe aus allen Verträgen liefern.

jobo 10. Jun 2013 13:42

AW: SQL: Jahresanteile des Vertags berechnen?
 
Zitat:

Zitat von DeddyH (Beitrag 1218028)
MS SQL 2012 ist doch angegeben.

Könnte schwören, das stand grad nicht da.:stupid:

romber 10. Jun 2013 18:27

AW: SQL: Jahresanteile des Vertags berechnen?
 
Für einen SQL-Beispel wäre ich sehr dankbar! :roll:

DeddyH 10. Jun 2013 18:34

AW: SQL: Jahresanteile des Vertags berechnen?
 
Wenn das überhaupt mit einer Abfrage (statt einer Stored Procedure) machbar ist, wird es wohl mächtig kompliziert. Ich habe zumindest keinen zündenden Einfall.

romber 10. Jun 2013 18:48

AW: SQL: Jahresanteile des Vertags berechnen?
 
Von mir aus kann das auch eine SP sein. Danke!

jobo 10. Jun 2013 19:07

AW: SQL: Jahresanteile des Vertags berechnen?
 
Interessantes Problem, ich bin in MSSQL nicht so fit und die Datumsarithmetik hat auf Anhieb nicht geklappt (Rangeerror). Muss aber nichts heißen.

Hier eine Oracle Lösung, die Hälfte des Codes kann man weglassen, ist nur Erklärung bzw Daten.
- fn "Round()" ggF durch mssql variante ersetzen
- "from dual" weglassen
- "decode" durch "case when" ersetzen
- Datumsberechnung durch anloge mssql function ersetzen
- fn "to_date()" durch "cast" ersetzen, später durch Datumsparameter
dann müsste es unter mssql laufen

Noch was zum Aufbau:
Ich hab vermieden, das Datum zu zerschnippeln (ala YYYY='2012' usw), ich hoffe so bekommst Du gute Performance trotz großer Datenmengen.
Da [myEnde] bei Dir nicht explizit vorliegt, sollte man es in der inneren Where Bedingung auf einen Vergleich mit [Mystart]<@ParamIntervalStart+Laufzeit umbauen.
Die Logik (where Bedingung und Decode/Case) funktioniert (hoffentlich) nur bei sinnvollen Intervall Werten und.
Sollte unabhängig von Intervallgrößen und Datumsgrenzen funktionieren.

Code:
select z.* ,
       round(z.TageDiff/30,0) as MonateIn,
       (Preis/Laufzeit)*round(z.TageDiff/30,0) as PreisIntervall
  from (
        select y.*, -- DefinedType = Manuell vordefiniert, zur Kontrolle
                    -- DefinedType muss durch CalcType ersetzbar sein mit gleichem Ergebnis
               decode(Definedtype,'I Ende überlappend', (to_date('31.12.2012','DD.MM.YYYY')/*IntervallEnd*/ - y.myStart),
                                  'I Start überlappend', (y.myEnde-to_date('01.01.2012','DD.MM.YYYY')/*IntervallStart*/ ),
                                  'eingeschlossen von I', y.myEnde-y.myStart,
                                  'I umschließend', to_date('31.12.2012','DD.MM.YYYY')/*IntervallEnd*/-  to_date('01.01.2012','DD.MM.YYYY')/*IntervallStart*/,
                                   -1/*error*/) as TageDiff,
               100.0 as Preis,
               round((MyEnde-MyStart)/30,0) as Laufzeit
          from (
                select x.*,
                       decode(-- MyStart kleiner als Intervallstart?
                              least(MyStart, to_date('01.01.2012','DD.MM.YYYY')/*IntervallStart*/),
                                    MyStart, /*'ja, kleiner Case'*/ decode(greatest(MyEnde, to_date('31.12.2012','DD.MM.YYYY')/*IntervallStart*/),
                                                                              MyEnde, 'I umschließend','I Start überlappend'),
                                             /*'ne, größer Case'*/ decode(greatest(MyEnde, to_date('31.12.2012','DD.MM.YYYY')/*IntervallStart*/),
                                                                              MyEndE, 'I Ende überlappend','eingeschlossen von I')
                              ) as CalcType
                  from (
                        select 'vor I'               as DefinedType, to_date('01.02.2011','DD.MM.YYYY') as myStart, to_date('30.04.2011','DD.MM.YYYY')  as myEnde from dual union
                        select 'hinter I'            as DefinedType, to_date('01.02.2015','DD.MM.YYYY') as myStart, to_date('01.05.2015','DD.MM.YYYY')  as myEnde from dual union
                        select 'I umschließend'      as DefinedType, to_date('01.02.2011','DD.MM.YYYY') as myStart, to_date('01.05.2013','DD.MM.YYYY')-1 as myEnde from dual union
                        select 'eingeschlossen von I' as DefinedType, to_date('01.02.2012','DD.MM.YYYY') as myStart, to_date('01.05.2012','DD.MM.YYYY')-1 as myEnde from dual union
                        select 'I Start überlappend' as DefinedType, to_date('01.02.2011','DD.MM.YYYY') as myStart, to_date('01.05.2012','DD.MM.YYYY')-1 as myEnde from dual union
                        select 'I Ende überlappend'  as DefinedType, to_date('01.02.2012','DD.MM.YYYY') as myStart, to_date('01.05.2013','DD.MM.YYYY')-1 as myEnde from dual
                        )x
                 where not x.myEnde < to_date('01.01.2012','DD.MM.YYYY') /*IntervallStart*/
                   and not x.myStart > to_date('31.12.2012','DD.MM.YYYY') /*IntervallEnde */
               ) y
       ) z

tgvoelker 10. Jun 2013 19:31

AW: SQL: Jahresanteile des Vertags berechnen?
 
Code:
SELECT
V.ID
,V.ANFANG
,V.DAUER
,V.BETRAG
,BERTRAG2012=
 CASE WHEN (DATEADD(month,V.DAUER,V.ANFANG)<'01/01/2012')OR(V.ANFANG>'31/12/2012')THEN 0
      WHEN (DATEADD(month,V.DAUER,V.ANFANG)<='31/12/2012')AND(V.ANFANG>='01/01/2012')THEN 1
      WHEN (V.ANFANG<'01/01/2012')AND(DATEADD(month,V.DAUER,V.ANFANG)<='31/12/2012')THEN CAST(DATEDIFF(day,'01/01/2012',DATEADD(month,V.DAUER,V.ANFANG)) AS NUMERIC(18,8))/DATEDIFF(day,V.ANFANG,DATEADD(month,V.DAUER,V.ANFANG))
      WHEN (V.ANFANG>='01/01/2012')AND(DATEADD(month,V.DAUER,V.ANFANG)>'31/12/2012')THEN CAST(DATEDIFF(day,V.ANFANG,'31/12/2012') AS NUMERIC(18,8))/DATEDIFF(day,V.ANFANG,DATEADD(month,V.DAUER,V.ANFANG))
 END * V.BETRAG
FROM
VERTRAEGE AS V

Bummi 10. Jun 2013 19:32

AW: SQL: Jahresanteile des Vertags berechnen?
 
Wenn Verträge auch innerhalb eines Monats beginnen können musst Du aufbohren / umbauen


Code:
/*  einmalig zu erstellende Function

Create Function EncodeDate( @day int,@month int,@year int) Returns DateTime
begin
 Declare @Result DateTime
 SELECT @Result=CAST(CAST(10000*@year+100*@month+@day AS VARCHAR(8)) AS DATETIME);
 Return @Result
end;

*/


Declare @Months Table(y int,m int)
insert into @Months values (2012,1),(2012,2),(2012,3),(2012,4),(2012,5),(2012,6),(2012,7),(2012,8),(2012,9),(2012,10),(2012,11),(2012,12)



Declare @a Table (ID int,Anfangsdatum datetime,Vertragsdauer int,[Bezahlter Betrag] money)
insert into @a Values(1,'20111101',12,100),(2,'20120101',3,100),(3,'20120601',12,100);



Select ID,COUNT(*) as Monate,[Bezahlter Betrag]/Vertragsdauer * COUNT(*) as Betrag
from
(
Select ID, Anfangsdatum,DATEADD(mm,Vertragsdauer,Anfangsdatum)-1 as EndDatum,[Bezahlter Betrag],Vertragsdauer
from @a
) a
join @Months m on Anfangsdatum<= dbo.EncodeDate(1,m.m,m.y) and Enddatum>= dbo.EncodeDate(1,m.m,m.y)
Group by ID,Vertragsdauer,[Bezahlter Betrag]

romber 10. Jun 2013 19:42

AW: SQL: Jahresanteile des Vertags berechnen?
 
:thumb:
Vielen Dank an alle! Ich muss jetzt alles ausprobieren!
Danke!!!

Furtbichler 10. Jun 2013 20:14

AW: SQL: Jahresanteile des Vertags berechnen?
 
--- blödsinn ---

tgvoelker 10. Jun 2013 20:19

AW: SQL: Jahresanteile des Vertags berechnen?
 
Nochmal kommentiert:
Code:
SELECT
V.ID
,V.ANFANG
,V.DAUER
,V.BETRAG
,BERTRAG2012=
 CASE WHEN (DATEADD(month,V.DAUER,V.ANFANG)<'01/01/2012')OR(V.ANFANG>'31/12/2012')THEN 0
      WHEN (DATEADD(month,V.DAUER,V.ANFANG)<='31/12/2012')AND(V.ANFANG>='01/01/2012')THEN 1
      WHEN (V.ANFANG<'01/01/2012')AND(DATEADD(month,V.DAUER,V.ANFANG)<='31/12/2012')THEN CAST(DATEDIFF(day,'01/01/2012',DATEADD(month,V.DAUER,V.ANFANG)) AS NUMERIC(18,8))/DATEDIFF(day,V.ANFANG,DATEADD(month,V.DAUER,V.ANFANG))
      WHEN (V.ANFANG>='01/01/2012')AND(DATEADD(month,V.DAUER,V.ANFANG)>'31/12/2012')THEN CAST(DATEDIFF(day,V.ANFANG,'31/12/2012') AS NUMERIC(18,8))/DATEDIFF(day,V.ANFANG,DATEADD(month,V.DAUER,V.ANFANG))
 END * V.BETRAG
FROM
VERTRAEGE AS V
Diese Syntax funktioniert auch bei Verträgen, die mitten im Monat anfangen.

Betrag_2012 multipliziert den Betrag mit einem Wert. Dieser Wert ist:
  • 0, wenn Anfangsdatum nach dem 31.12.2012 oder Ende vor dem 1.1.2012
  • 1, wenn Anfangsdatum gleich oder nach dem 1.1.2012 und enddatum gleich oder vor dem 31.12.2012
  • Quotient aus den Tagen zwischen 1.1.2012 und Ende und Gesamttagen, wenn Anfang vor dem 1.1.2012 und ende gleich oder vor dem 31.12.2012 (Vertrag außerhalb 2012 wurde schon im ersten Punkt behandelt!))
  • Quotient aus den Tagen zwischen Anfang und 31.12.2012 und Gesamttagen, wenn Anfange nach dem 1.1.2012 und Ende nach dem 31.12.2012

Die Umwandlung des Dividenden in Numeric(18,8) hat den Hintergrund, daß sonst das Ergebnis in INT umgewandelt würde.

Ist auf SQL Server 2005 getestet.

Das Ergebnis ist abweichend von einer Implementierung auf Basis ganzer Monate (wenn Verträge immer am 01. beginnen würden). In diesem Fall wäre anstelle von DATEDIFF(day... DATEDIFF(month... zu verwenden.

tgvoelker 10. Jun 2013 20:20

AW: SQL: Jahresanteile des Vertags berechnen?
 
Zitat:

Zitat von Furtbichler (Beitrag 1218107)
--- blödsinn ---

O_o

sx2008 10. Jun 2013 20:34

AW: SQL: Jahresanteile des Vertags berechnen?
 
Zitat:

Zitat von romber (Beitrag 1218019)
Mangels tiefgreifender SQL-Kenntnisse liste ich testweise alle Vertäge auf und führe für jeden Vertrag die o.g. Schritte aus.

Du kannst alle Verträge vor dem 1.1.2011 (= 01.01.2012 - maxVertragslaufzeit) per SQL wegfiltern.
Das müsste die Menge der Datensätze beträchtlich reduzieren.

Manche Dinge lassen sich einfach besser mit einer "richtigen" Programmiersprache berechnen und sind in SQL eine Quälerei.
Wenn deine Zigarettenpause auf <= 20 Sekunden schrumpft dann würde ich bei der Clientseitigen Lösung bleiben.

Auf jeden Fall solltest du vermeiden, den Restbetrag mit SQL zu berechnen.
Man kann alles mit SQL machen (Quälerei) oder alles mit Delphi (langsam) oder man filtert nur alle Datensätze, die im Jahr 2012 noch laufen und bewerkstelligt die Berechnung mit einem Calculated Field (schnell & flexibel).

nahpets 10. Jun 2013 21:22

AW: SQL: Jahresanteile des Vertags berechnen?
 
Hallo,

hier mal ein Versuch:

Folgende Annahme:

Die Monate werden immer vollständig berechnet und nicht taggenau.

Beispiel: Für Anfangsdatum 01.08.2012 bei einer Vertragsdauer von 6 Monaten entfallen 5 Monate auf das Jahr 2012.
Beispiel: Für Anfangsdatum 31.08.2012 bei einer Vertragsdauer von 6 Monaten entfallen 5 Monate auf das Jahr 2012.

Für den August entfallen auf das Jahr 2012 bei einer Dauer von
1 = 1 Monat
3 = 3 Monate
6 = 5 Monate
12 = 5 Monate.

Dies entspricht dem kleineren Wert von Vertragsdauer und (12 - Monat + 1).
Auf das Jahr 2013 entfallen demnach 12 - diesem Wert.

(Das Beispiel ist nicht getestet sondern nur im Editor so hingeschrieben. Das SQL-Statement bitte von innen nach außen lesen.)

Code:
/* Die Summen für alle Verträge, bei denen der Vertrag im Jahr beginnt oder endet. */
select
  sum(BetragStartJahr) as BetragStartJahr,
  sum(BetragEndeJahr) as BetragEndeJahr
from (
  /* Nun die Anteile der bezahlten Beträge für das Beginnjahr und das Endejahr berechnen. */
  select
    Anfangsdatum,
    Vertragsdauer,
    BezahlterBetrag,
    Monat,
    StartJahr,
    EndeJahr,
    DauerStartJahr,
    DauerEndeJahr,
    BezahlterBetrag / 12 * DauerStartJahr as BetragStartJahr,
    BezahlterBetrag / 12 * DauerEndeJahr as BetragEndeJahr
  from (
    /* Feststellen, wieviele Monate auf das Jahr des Vertragsbeginnes entfallen */
    /* bzw. auf das Jahr des Vertragsendes. */
    select
      Anfangsdatum,
      Vertragsdauer,
      BezahlterBetrag,
      Monat,
      StartJahr,
      EndeJahr,
      min(Vertragsdauer,(12 - Monat + 1)) as DauerStartJahr,
      12 - min(Vertragsdauer,(12 - Monat + 1)) as DauerEndeJahr
    from (
      /* Zuerst Monat und Jahr des Vertragsbeginnes bzw. Endes ermitteln. */
      select
        Anfangsdatum,
        Vertragsdauer,
        BezahlterBetrag,
        month(Anfangsdatum) as Monat,
        year(Anfangsdatum) as StartJahr,
        year(Anfangsdatum) + 1 as EndeJahr
      from testtabelle
      /* Eventuell hier schon das Jahr per SQL einschränken? */
      /* where year(anfangsdatum) between :ParameterJahr - 1 and :ParameterJahr + 1 */
    ) a
  ) b
  /* Auswahlmenge auf das gewünschte Jahr einschränken. */
  where StartJahr = :ParameterJahr
  or   EndeJahr = :ParameterJahr
) c
Wenn's denn funktionieren sollte, so funktioniert es auch noch in 100 Jahren, da die Jahreszahl per Parameter an das SQL übergeben wird.

Eventuell geht's auch noch etwas kürzer, aber nicht zwingend lesbarer (und durch redundante Berechnungen eventuell langsamer?):
Code:
/* Die Summen für alle Verträge, bei denen der Vertrag im Jahr beginnt oder endet. */
select
  sum(BetragStartJahr) as BetragStartJahr,
  sum(BetragEndeJahr) as BetragEndeJahr
from (
  /* Monat und Jahr des Vertragsbeginnes bzw. Endes ermitteln. */
  /* Feststellen, wieviele Monate auf das Jahr des Vertragsbeginnes entfallen */
  /* bzw. auf das Jahr des Vertragsendes. */
  /* Die Anteile der bezahlten Beträge für das Beginnjahr und das Endejahr berechnen. */
  select
    Anfangsdatum,
    Vertragsdauer,
    BezahlterBetrag,
    year(Anfangsdatum) as StartJahr,
    year(Anfangsdatum) + 1 as EndeJahr,
    BezahlterBetrag / 12 * (min(Vertragsdauer,(12 - month(Anfangsdatum) + 1))) as BetragStartJahr,
    BezahlterBetrag / 12 * (12 - min(Vertragsdauer,(12 - month(Anfangsdatum) + 1)) as BetragEndeJahr
  from testtabelle
  where year(anfangsdatum) between :ParameterJahr - 1 and :ParameterJahr + 1
) a
/* Auswahlmenge auf das gewünschte Jahr einschränken. */
where StartJahr = :ParameterJahr
or   EndeJahr = :ParameterJahr

Furtbichler 11. Jun 2013 08:51

AW: SQL: Jahresanteile des Vertags berechnen?
 
Ich glaube, es geht kürzer:
SQL-Code:
---
--- Testumgebung ----------------------------------------------------------
---
USE [Test]
GO

CREATE TABLE [dbo].[Contracts](
   [ctID] [int] IDENTITY(1,1) NOT NULL,
   [ctStart] [smalldatetime] NOT NULL,
   [ctDurationMonths] [int] NOT NULL,
   [ctPrice] [money] NOT NULL,
   [soll] [int] NULL
) ON [PRIMARY]


declare @startPeriod dateTime
declare @EndPeriod DateTime
set @startPeriod='20120101'
set @EndPeriod = '20121231'

--- Abfrage ---------------------------------------------------------------------------
select *, ctPrice*DateDiff(Month, dmin,dmax)/ctDurationMonths as PriceInPeriod
from
(
select *,
   (select max (X) from (values (@StartPeriod), (ctStart)) as T(X)) dMin,
   (select min (X) from (values (@EndPeriod), (DateAdd(Month, ctDurationMonths, ctStart))) as T(X)) dMax
----------*****---- Hier war ein Tippfehler. Danke tgvoelker!   
 from contracts
 ) x
 where DateDiff(Month, dmin,dmax)>0
--------------------------------------------------------------------------------------

tgvoelker 12. Jun 2013 07:02

AW: SQL: Jahresanteile des Vertags berechnen?
 
Zitat:

Zitat von Furtbichler (Beitrag 1218147)
Ich glaube, es geht kürzer:
SQL-Code:
---
--- Testumgebung ----------------------------------------------------------
---
USE [Test]
GO

CREATE TABLE [dbo].[Contracts](
   [ctID] [int] IDENTITY(1,1) NOT NULL,
   [ctStart] [smalldatetime] NOT NULL,
   [ctDurationMonths] [int] NOT NULL,
   [ctPrice] [money] NOT NULL,
   [soll] [int] NULL
) ON [PRIMARY]


declare @startPeriod dateTime
declare @EndPeriod DateTime
set @startPeriod='20120101'
set @EndPeriod = '20121231'

--- Abfrage ---------------------------------------------------------------------------
select *, ctPrice*DateDiff(Month, dmin,dmax)/ctDurationMonths as PriceInPeriod
from
(
select *,
   (select max (X) from (values (@StartPeriod), (ctStart)) as T(X)) dMin,
   (select max (X) from (values (@EndPeriod), (DateAdd(Month, ctDurationMonths, ctStart))) as T(X)) dMax
   
 from contracts
 ) x
 where DateDiff(Month, dmin,dmax)>0
--------------------------------------------------------------------------------------

Was ist das Ergebnis, wenn der Vertrag am 01.06.2013 anfängt und 1 Monat läuft?
Was ist das Ergebnis, wenn der Vertrag am 01.12.2011 anfängt und 3 monate läuft?

:>

Furtbichler 12. Jun 2013 08:19

AW: SQL: Jahresanteile des Vertags berechnen?
 
Moin,
Danke fürs Testen.
Da war noch ein Tippfehler beim Refaktorisieren.

Hier die korrekte Version (war ja zu deutlich):

SQL-Code:
select *, ctPrice*DateDiff(Month, dmin,dmax)/ctDurationMonths as PriceInPeriod
from
 (
select *,
    (select max (X) from (values (@StartPeriod), (ctStart)) as T(X)) dMin,
    (select min (X) from (values (@EndPeriod), (DateAdd(Month, ctDurationMonths, ctStart))) as T(X)) dMax
-----------****----- hier stand 'max'
  from contracts
  ) x
  where DateDiff(Month, dmin,dmax)>0

generic 12. Jun 2013 17:04

AW: SQL: Jahresanteile des Vertags berechnen?
 
Die Lösung in #20 ist gut! Lob!

Die Datumermittlung ist pfiffig, mit dem Subquerys und values.

Anfangs- und Ende-Überlappungen berücksichtigt und natürlich den Einschluss-Zeitraum.
Funktionieren kann es nur nicht wenn der Vertrag länger als 12 Monate laufen könnte, dass ist hier ja aber nicht Anforderung gewesen.

Man könnte die Selects noch in eine UDF auslagern.
http://stackoverflow.com/questions/1...math-max-in-ne

Furtbichler 12. Jun 2013 21:54

AW: SQL: Jahresanteile des Vertags berechnen?
 
Zitat:

Zitat von generic (Beitrag 1218392)
Funktionieren kann es nur nicht wenn der Vertrag länger als 12 Monate laufen könnte, dass ist hier ja aber nicht Anforderung gewesen.

Verstehe nicht, wieso das nicht laufen sollte. Ich habe es mit irgendwelchen krummen Laufzeiten getestet und da der Zeitraum eh gemappt wird, nämlich auf den Anfangs/Endzeitraum, müsste das funktionieren. Aber Gegenbeispiele -oder eine Erklärung- sind natürlich immer besser. Hast Du eines?

tgvoelker 13. Jun 2013 11:30

AW: SQL: Jahresanteile des Vertags berechnen?
 
generic, FBs Source funktioniert durchaus, wenngleich mir der SQL Server 2012 zum testen fehlt. Logisch ist das einwandfrei, sofern Verträge immer nur zum 1. beginnen können:

* Als erstes wird für jede Zeile entweder der 1.1.2012 oder das Anfangsdatum zurückgegeben, je nachdem, was größer ist
* dann wird das Enddatum oder der 31.12. zurückgegeben, je nachdem, was kleiner ist.
* dann fliegen alle die raus, bei denen nicht mindestens 1 Monat (Rundungsverhalten DateDiff? - bei Verträgen, die mitten im Monat beginnen) zwischen Anfang und Ende liegt.

Wenn Anfang nach dem 31.12.2012, dann fliegt der Tupel raus, weil dmax<dmin
Wenn Ende vor dem 1.1.2012, dann fliegt der Tupel raus, weil dmax<dmin
Wenn Anfang nach dem 1.1.2012 und Ende davor, dann ist dmin der richtige Anfang und dmax das richtige Ende.
Wenn Anfang vor dem 1.1.2012 und Ende zwischen 1.1.und 31.12., dann ist dmin 1.1. und dmax das richtige Ende
Wenn Anfang zwischen 1.1. und 31.12. und Ende danach, dann ist dmin der richtige Anfang und dmax 31.12.

Paßt also alles.

Ich würde das zwar anders machen (s.o.), weil ich meist alle Tupel haben und bei denen, die nicht betroffen sind, eine 0 drinstehen haben möchte, aber das ist kosmetisch.

generic 13. Jun 2013 11:58

AW: SQL: Jahresanteile des Vertags berechnen?
 
Wie gesagt, war nicht Anforderung.

Wenn ein Vertrag länger als 12 Monate wäre, dann würde die Daten raus fallen. Wie du schreibst.
Anteilig müsste so ein Vertrag aber mit 12 Monatsbeiträgen berechnet werden.

Kommt nun auf das Verwaltungssystem an, es ist aber normal das ein Vertrag immer für 1 Jahr geschlossen wird und dann nur pro Jahr verlängert wird bzw. erneuert wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz