我有一个返回两列的TVF:'measure'(一个名字)和'score',这个指标的数字分数:
dbo.ScoringFunction(param1, param2, ..., paramN)
Measure Score
------- -----
measure1 10
measure2 5
... ...
measureN 15
我正在针对包含其参数的大量行运行此函数:
Name Param1 Param2 ... ParamN
---- ------ ------ ------
Daniel 12 5 6
etc.
我正在尝试找到一种方法来显示决定这些分数的参数旁边的度量及其分数:
Name Param1 Param2 ... ParamN measure1 measure2 ... measureN
---- ------ ------ ------ -------- -------- --------
Daniel 12 5 6 10 5 15
etc.
到目前为止,我已尝试使用数据透视表,但由于数据被转动包含在TVF而不是静态表中,所以它很棘手。我也尝试过使用CROSS APPLY,但是一旦我掌握了数据(测量和分数),我仍然无法将其转换为格式良好的行。
如果有人有任何想法,我们将不胜感激!
答案 0 :(得分:0)
如果你创建一个如下所示的函数:
CREATE FUNCTION [dbo].[fGetSpecificMeasures]
(
@HeightScore INT
, @WeightScore INT
, @TvScore INT
)
RETURNS TABLE
RETURN
(
SELECT
Final.Height AS tv_height_score
, Final.[Weight] AS tv_weight_score
, Final.TV AS tv_score
FROM
(
SELECT measure, score FROM ScoringRubric WHERE measure = 'Height' AND @HeightScore BETWEEN bottom_of_range AND top_of_range
UNION ALL
SELECT measure, score FROM ScoringRubric WHERE measure = 'Weight' AND @WeightScore BETWEEN bottom_of_range AND top_of_range
UNION ALL
SELECT measure, score FROM ScoringRubric WHERE measure = 'TV' AND @TvScore BETWEEN bottom_of_range AND top_of_range
) Base
PIVOT
(
MAX(score)
FOR measure
IN
(
[Height]
, [Weight]
, [TV]
)
) Final
);
GO
看起来像这样:
CREATE FUNCTION [dbo].[fGetMeasureScore]
(
@Measure VARCHAR(50)
, @Value INT
)
RETURNS TABLE
RETURN
(
SELECT
score
FROM ScoringRubric
WHERE measure = @Measure
AND @Value BETWEEN bottom_of_range AND top_of_range
);
GO
然后,您可以使用以下任一方式获取数据:
DECLARE @User VARCHAR(50) = 'Daniel'
SELECT
UserProfile.*
, HeightScore.score AS tv_height_score
, WeightScore.score AS tv_weight_score
, TvScore.score AS tv_score
FROM UserProfile
INNER JOIN ScoringRubric HeightScore
ON HeightScore.measure = 'Height'
AND UserProfile.height BETWEEN HeightScore.bottom_of_range AND HeightScore.top_of_range
INNER JOIN ScoringRubric WeightScore
ON WeightScore.measure = 'Weight'
AND UserProfile.[weight] BETWEEN WeightScore.bottom_of_range AND WeightScore.top_of_range
INNER JOIN ScoringRubric TvScore
ON TvScore.measure = 'TV'
AND UserProfile.TV BETWEEN TvScore.bottom_of_range AND TvScore.top_of_range
WHERE UserProfile.name = @User
SELECT
*
FROM UserProfile
CROSS APPLY dbo.fGetSpecificMeasures(height, [weight], TV)
WHERE name = @User
SELECT
UP.*
, HeightScore.score AS tv_height_score
, WeightScore.score AS tv_weight_score
, TvScore.score AS tv_score
FROM UserProfile UP
CROSS APPLY fGetMeasureScore('Height', UP.height) HeightScore
CROSS APPLY fGetMeasureScore('Weight', UP.[weight]) WeightScore
CROSS APPLY fGetMeasureScore('TV', UP.TV) TvScore
WHERE UP.name = @User
我真的不知道哪一种你最适合你的用途。如果您有疑问,请告诉我。
至于你原来的问题,如果这是功能:
CREATE FUNCTION [dbo].[fGetMeasureScoresOriginal]
(
@HeightScore INT
, @WeightScore INT
, @TvScore INT
)
RETURNS TABLE
RETURN
(
SELECT measure, score FROM ScoringRubric WHERE measure = 'Height' AND @HeightScore BETWEEN bottom_of_range AND top_of_range
UNION ALL
SELECT measure, score FROM ScoringRubric WHERE measure = 'Weight' AND @WeightScore BETWEEN bottom_of_range AND top_of_range
UNION ALL
SELECT measure, score FROM ScoringRubric WHERE measure = 'TV' AND @TvScore BETWEEN bottom_of_range AND top_of_range
)
GO
然后您可以像这样编写查询和数据透视:
SELECT
Final.name
, Final.OriginalHeight AS height
, Final.OriginalWeight AS [weight]
, Final.OriginalTv AS TV
, Final.Height AS tv_height_score
, Final.[Weight] AS tv_weight_score
, Final.TV AS tv_score
FROM
(
SELECT
UP.name
, UP.height AS OriginalHeight
, UP.[weight] AS OriginalWeight
, UP.TV AS OriginalTv
, Measures.measure
, Measures.score
FROM UserProfile UP
CROSS APPLY dbo.fGetMeasureScoresOriginal(UP.height, UP.[weight], UP.TV) Measures
WHERE UP.name = @User
) Base
PIVOT
(
MAX(score)
FOR measure
IN
(
[Height]
, [Weight]
, [TV]
)
) Final
编辑:刚才意识到我没有回答原来的问题。现在添加。
答案 1 :(得分:0)
如果要转动静态行集,可以使用我所描述的技术here。
重新发布示例,因此它将是不同的表格,但我认为该技术也适用于您的情况。
SELECT
Customers.CustID,
MAX(CASE WHEN CF.FieldID = 1 THEN CF.FieldValue ELSE NULL END) AS Field1,
MAX(CASE WHEN CF.FieldID = 2 THEN CF.FieldValue ELSE NULL END) AS Field2,
MAX(CASE WHEN CF.FieldID = 3 THEN CF.FieldValue ELSE NULL END) AS Field3,
MAX(CASE WHEN CF.FieldID = 4 THEN CF.FieldValue ELSE NULL END) AS Field4
-- Add more...
FROM Customers
LEFT OUTER JOIN CustomFields CF
ON CF.ID = Customers.CustID
WHERE Customers.CustName like 'C%'
GROUP BY Customers.CustID
答案 2 :(得分:0)
如果不改变太多(希望如此),我会在函数中进行旋转,然后使用CROSS APPLY中的函数并拉出列。所以,如果你的功能是这样的:
CREATE FUNCTION dbo.ScoringFunction (parameters)
RETURNS TABLE
RETURN (
SELECT Measure, Score
FROM …
)
然后我会像这样重写它:
CREATE FUNCTION dbo.ScoringFunction (parameters)
RETURNS TABLE
RETURN (
WITH originalSelect AS (
SELECT Measure, Score
FROM …
)
SELECT
measure1,
measure2,
…
FROM originalSelect
PIVOT (
MAX(Score) FOR Measure IN (measure1, measure2, …)
) p
)
并在最终查询中使用它,如下所示:
SELECT
t.Name,
t.param1,
t.param2,
…
x.measure1,
x.measure2,
…
FROM atable t
CROSS APPLY dbo.ScoringFunction (t.param1, t.param2, …) x