[英]Group by ranges in SQL Server
我有范圍的分組問題。 我試圖將結果分組為每10瑞典克朗(瑞典克朗)。 問題是當PriceSEK匹配LowerBoundSEK和UpperBoundSEK時。
如下所示,我添加了-0.001,目前只是作為所需結果的直觀表示。 它仍然按0.1分組。
如何調整此分組以獲得在正確范圍內計數兩次的所需結果0.4? (0.301-0.4)
http://sqlfiddle.com/#!6/f7624/3
測試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
編輯:
期望的結果:
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
我用更多測試解決了它。 最大的變化是CEILING
並將JOIN
更改為遠程連接。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.