Quassnoi pokazuje jak wykonać SUMPRODUCT, a przy użyciu WHERE pozwoliłoby na ograniczenie przez pole data ...
SELECT
SUM([tbl].data * [tbl].weight)/SUM([tbl].weight)
FROM
[tbl]
WHERE
[tbl].date >= '2009 Jan 01'
AND [tbl].date < '2010 Jan 01'
Bardziej złożona część to miejsce, w którym chcesz "dynamicznie określić", jakie pole to [dane], a jakie pole [waga]. Krótka odpowiedź brzmi, że realistycznie musisz skorzystać z Dynamic SQL. Coś wzdłuż linii:
- Tworzenie ciąg szablon
- Wymienić wszystkie instancje [TBL] .data z pola odpowiednie dane
- Wymienić wszystkie instancje [TBL] .weight z odpowiednim polu wagi
- Wykonaj jednak ciąg znaków dynamiczny SQL, jednak wykonuje swój własny narzut. Czy zapytania są stosunkowo rzadkie lub czas wykonania samego zapytania jest stosunkowo długi, może to nie mieć znaczenia. Jeśli jednak są one powszechne i krótkie, można zauważyć, że użycie sql dynamicznego wprowadza istotne obciążenie. (Nie wspominając uważając ataków SQL injection, itp)
EDIT:
W swojej najnowszej przykład wyróżnić trzy pola:
- RecordDate
- KPI
- Rzeczywisty
Gdy [KPI] to "Waga Y ", a następnie [Rzeczywisty] Współczynnik ważenia do użycia.
Gdy [KPI] to "Tony zmielone", wówczas [Rzeczywiste] to Dane, które chcesz zebrać.
Kilka pytań mam to:
- Czy są jakieś inne pola?
- Czy jest tylko JEDNA rzeczywisty na dzień na KPI?
Powodem, dla którego pytam, że chcesz upewnić się, że DOŁĄCZ występuje, jest tylko 1: 1.(Nie chcesz 5 Rzeczywiste łączenia z 5 Wag, dając rekordy 25 resultsing)
Niezależnie nieznaczne uproszczenie zapytaniu jest z pewnością możliwe ...
SELECT
SUM([baseSeries].Actual * [weightSeries].Actual)/SUM([weightSeries].Actual)
FROM
CalcProductionRecords AS [baseSeries]
INNER JOIN
CalcProductionRecords AS [weightSeries]
ON [weightSeries].RecordDate = [baseSeries].RecordDate
-- AND [weightSeries].someOtherID = [baseSeries].someOtherID
WHERE
[baseSeries].KPI = 'Tons Milled'
AND [weightSeries].KPI = 'Weighty'
zakomentowanym potrzebne tylko wtedy, gdy linia potrzebujesz dodatkowych predykatów, aby zapewnić relację 1: 1 między danymi a wagami.
Jeśli nie można guarnatee tylko jedna wartość na bieżąco, i nie ma żadnych innych pól, aby dołączyć, możesz zmodyfikować sub_query wersja nieznacznie opiera ...
SELECT
SUM([baseSeries].Actual * [weightSeries].Actual)/SUM([weightSeries].Actual)
FROM
(
SELECT
RecordDate,
SUM(Actual)
FROM
CalcProductionRecords
WHERE
KPI = 'Tons Milled'
GROUP BY
RecordDate
)
AS [baseSeries]
INNER JOIN
(
SELECT
RecordDate,
AVG(Actual)
FROM
CalcProductionRecords
WHERE
KPI = 'Weighty'
GROUP BY
RecordDate
)
AS [weightSeries]
ON [weightSeries].RecordDate = [baseSeries].RecordDate
Zakłada to, że AVG wagi jest poprawny, jeśli istnieje wiele wag na ten sam dzień.
EDIT: Ktoś po prostu głosowali na to tak myślałem, że poprawić ostateczną odpowiedź :)
SELECT
SUM(Actual * Weight)/SUM(Weight)
FROM
(
SELECT
RecordDate,
SUM(CASE WHEN KPI = 'Tons Milled' THEN Actual ELSE NULL END) AS Actual,
AVG(CASE WHEN KPI = 'Weighty' THEN Actual ELSE NULL END) AS Weight
FROM
CalcProductionRecords
WHERE
KPI IN ('Tons Milled', 'Weighty')
GROUP BY
RecordDate
)
AS pivotAggregate
ten sposób unika JOIN i również tylko skanuje tabelę raz.
Opiera się na tym, że wartości NULL
są ignorowane podczas obliczania wartości AVG()
.
jaki zakres dat przyjść do niego? Ile kolumn - kilka lub wiele części? Czy ustalono liczbę kolumn? –
@martin, tylko jedna kolumna. Kiedyś był jeden na KPI, ale to nie było zabawne. Zakres dat dotyczy okresu raportowania. – ProfK
Czy powyższe stwierdzenie jest uważane za CTE? Jeśli nie, to jak możesz zmienić to w CTE? Ktoś? – PositiveGuy