2016-10-06 4 views
1

Ich habe ein Gruppierungsproblem mit Bereichen. Ich versuche das Ergebnis in jeder 10. SEK (Schwedische Krone) zu gruppieren. Problem ist, wenn der PriceSEK mit LowerBoundSEK und UpperBoundSEK übereinstimmt.Gruppieren nach Bereichen in SQL Server

Wie Sie unten sehen, habe ich -0.001 hinzugefügt, die im Moment nur als eine visuelle Darstellung des gewünschten Ergebnisses fungiert. Es gruppiert sich immer noch um 0,1.

Wie kann ich diese Gruppierung anpassen, um das gewünschte Ergebnis von 0,4 zweimal im richtigen Bereich zu erhalten? (0.301-0.4)

http://sqlfiddle.com/#!6/f7624/3

Test-SQL

CREATE TABLE #Test (
    ID int NOT NULL IDENTITY(1,1), 
    PriceEUROCent smallmoney NOT NULL, 
    DateSent datetime NOT NULL, 
    Quantity int NOT NULL, 
    SomeID int NOT NULL, 
    CurrencyID int NOT NULL 
) 

CREATE TABLE #Currencies (
    CurrencyID int IDENTITY(1, 1), 
    CurrencyValue numeric(17,3) 
) 

INSERT INTO #Currencies SELECT 10 --9.617 


INSERT INTO #Test 
    (PriceEUROCent, DateSent, Quantity, SomeID, CurrencyID) 
    VALUES 
     ('2.70', '2016-09-27 11:00', 1, 1, 1), 
     ('3.00', '2016-09-27 12:00', 1, 1, 1), 
     ('4.0', '2016-09-27 14:00', 1, 1, 1), 
     ('4.0', '2016-09-27 14:00', 1, 1, 1), 
     ('6.80', '2016-09-27 12:00', 1, 1, 1), 
     ('8.00', '2016-09-28 14:01', 3, 1, 1) 



DECLARE @RangeWidth numeric(17,3), @Currency numeric(17,3), @RangeWidthSEK numeric(17, 3) 

SET @RangeWidth = .1 

SELECT 
    DT.SomeID, 
    DT.LowerBoundSEK, 
    DT.UpperBoundSEK, 
    DT.SomeDate, 
    SUM(DT.Quantity) AS Quantity, 
    SUM(DT.SumPriceSEK) AS SumPriceSEK 
    FROM (
     SELECT 
      (PriceEUROCent/100) * C.CurrencyValue AS PriceSEK, 
      FLOOR((PriceEUROCent/10) * C.CurrencyValue) * @RangeWidth + 0.001 AS LowerBoundSEK, 
      (FLOOR((PriceEUROCent/10) * C.CurrencyValue) * @RangeWidth) + @RangeWidth AS UpperBoundSEK, 
      (FLOOR((PriceEUROCent/10) * C.CurrencyValue) * @RangeWidth) + @RangeWidth AS SumPriceSEK, 
      SomeID, 
      Quantity, 
      CONVERT(VARCHAR(10), DateSent, 120) AS SomeDate 
      FROM #Test T 
       JOIN #Currencies C ON T.CurrencyID = C.CurrencyID 
    ) DT 
    GROUP BY 
    FLOOR(DT.PriceSEK/@RangeWidth), 
    DT.SomeDate, 
    DT.LowerBoundSEK, 
    DT.UpperBoundSEK, 
    DT.SomeID 




-- DEBUG SELECT 
SELECT T.DateSent, T.Quantity, T.SomeID, C.CurrencyValue, 
    (PriceEUROCent/100) * C.CurrencyValue * T.Quantity AS PriceSEK, 
    PriceEUROCent * T.Quantity AS PriceEUROCent 
    FROM #Test T 
    JOIN #Currencies C ON T.CurrencyID = C.CurrencyID 

EDIT:

Wunschergebnis:

1 0.201 0.3 2016-09-27 2 0.300 
1 0.301 0.4 2016-09-27 2 0.800 
1 0.601 0.7 2016-09-27 1 0.700 
1 0.701 0.8 2016-09-28 3 2.400 
+0

was genau Ausgang wollen Sie? –

+1

Programmierempfehlung: alle FLOOR, CONVERT usw. in der abgeleiteten Tabelle tun. – jarlh

+0

@jarlh Oder noch besser - in einem CTE. – ajeh

Antwort

0

Ich löste es weitere Tests verwendet wird. Die größte Änderung war CEILING und die Änderung der JOIN zu einer Fernverbindung.

CREATE TABLE #Test (
    ID int NOT NULL IDENTITY(1,1), 
    PriceEUROCent smallmoney NOT NULL, 
    DateSent datetime NOT NULL, 
    Quantity int NOT NULL, 
    SomeID int NOT NULL, 
    CurrencyID int NOT NULL 
) 

CREATE TABLE #Currencies (
    CurrencyID int IDENTITY(1, 1), 
    CurrencyValue numeric(17,3) 
) 

INSERT INTO #Currencies SELECT 10 --9.617 


INSERT INTO #Test 
    (PriceEUROCent, DateSent, Quantity, SomeID, CurrencyID) 
    VALUES 
     ('1', '2016-09-27 11:00', 1, 1, 1), 
     ('2', '2016-09-27 11:00', 1, 1, 1), 
     ('2.200', '2016-09-27 12:00', 1, 1, 1), 
     ('2.999', '2016-09-27 12:00', 1, 1, 1), 
     ('3', '2016-09-27 12:00', 1, 1, 1), 
     ('4.0', '2016-09-27 14:00', 1, 1, 1), 
     ('4.0', '2016-09-27 14:00', 1, 1, 1), 
     ('6.80', '2016-09-27 12:00', 1, 1, 1), 
     ('7.1', '2016-09-27 14:01', 3, 1, 1) 


DECLARE @RangeWidth numeric(17,3) 

SET @RangeWidth = .1 

SELECT 
    R.SomeID, 
    R.DateSent, 
    R.LowerBoundSEK, 
    R.UpperBoundSEK, 
    SUM(R.UpperBoundSEK * T.Quantity) AS SumPrice, 
    SUM(T.Quantity) AS Quantity 
    FROM 
    (
     SELECT 
      T.SomeID, 
      C.CurrencyValue, 
      CONVERT(VARCHAR(10), T.DateSent, 120) AS DateSent, 
      (CEILING((PriceEUROCent/10) * C.CurrencyValue) 
       * @RangeWidth) + 0.001 - @RangeWidth 
        AS LowerBoundSEK, 
      (CEILING((PriceEUROCent/10) * C.CurrencyValue) * @RangeWidth) 
       AS UpperBoundSEK 
      FROM #Test T 
       JOIN #Currencies C ON T.CurrencyID = C.CurrencyID 
        GROUP BY 
         CEILING((PriceEUROCent/10) * C.CurrencyValue), 
         C.CurrencyValue, 
         T.SomeID, 
         CONVERT(VARCHAR(10), T.DateSent, 120) 
    ) R 
     JOIN #Test T ON (T.PriceEUROCent * R.CurrencyValue/100) 
          BETWEEN R.LowerBoundSEK AND R.UpperBoundSEK 
     GROUP BY 
      R.SomeID, 
      R.DateSent, 
      R.LowerBoundSEK, 
      R.UpperBoundSEK 
       ORDER BY 
        R.SomeID, 
        R.DateSent, 
        R.LowerBoundSEK 

DROP TABLE #Test 
DROP TABLE #Currencies 
Verwandte Themen