请考虑以下表格
Metric_Threshold 该表包含每个指标的阈值范围
+----------+--------------------+--------+---------+
| MetricId | Threshold_Category | Symbol | Values1 |
+----------+--------------------+--------+---------+
| Met1 | In SLA | > | 80 |
| Met1 | Mature | >= | 70 |
| Met1 | Satisfactory | >= | 60 |
| Met1 | Needs Improvement | < | 60 |
| Met2 | In SLA | = | Y |
| Met2 | Out of SLA | = | N |
| Met3 | Mature | = | 0 |
| Met3 | Needs Improvement | = | 1 |
| Met4 | In SLA | > | 80 |
| Met4 | Mature | >= | 70 |
| Met4 | Satisfactory | < | 60 |
| Met4 | Needs Improvement | < | 50 |
+----------+--------------------+--------+---------+
Metric_Report (该表包含每个月针对这些指标报告的值)。
+----------+----------------+---------------+
| MetricId | reporting_date | report_values |
+----------+----------------+---------------+
| Met1 | 2020-01-01 | 72.15 |
| Met2 | 2020-01-01 | Y |
| Met3 | 2020-01-01 | 0 |
| Met1 | 2020-02-01 | 80 |
| Met2 | 2020-02-01 | Y |
| Met3 | 2020-02-01 | 1 |
| Met1 | 2020-03-01 | 60 |
| Met2 | 2020-03-01 | Y |
| Met3 | 2020-03-01 | 1 |
| Met4 | 2020-03-01 | 50 |
+----------+----------------+---------------+
我正在尝试获取一个视图/查询,以将metric_report值归类到相应的范围内。
预期输出
+----------+----------------+---------------+-------------------+
| MetricId | reporting_date | report_values | Range |
+----------+----------------+---------------+-------------------+
| Met1 | 2020-01-01 | 72.15 | Mature |
| Met2 | 2020-01-01 | Y | In SLA |
| Met3 | 2020-01-01 | 0 | Mature |
| Met1 | 2020-02-01 | 80 | Mature |
| Met2 | 2020-02-01 | Y | In SLA |
| Met3 | 2020-02-01 | 1 | Needs Improvement |
| Met1 | 2020-03-01 | 60 | Needs Improvement |
| Met2 | 2020-03-01 | Y | In SLA |
| Met3 | 2020-03-01 | 1 | Mature |
| Met4 | 2020-03-01 | 50 | Satisfactory |
+----------+----------------+---------------+-------------------+
我面临的困难是我无法对每个指标的范围进行硬编码,因为这些值很可能会被用户修改
我可以使用动态sql来构造查询,然后将结果推送到临时表,然后按metric_report值显示类别
但是我想检查是否有一个选项可以在静态视图/查询本身中获取它。
更新的数据库小提琴链接 https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=43c39a4f88cd410f91e94f721ee7e75e
脚本
create table metric_threshold
( metric_id varchar(10)
, threshold_category varchar(30)
, symbol varchar(50)
, values1 varchar(20)
)
insert into metric_threshold values('Met1','In SLA','>','80')
insert into metric_threshold values('Met1','Mature','>=','70')
insert into metric_threshold values('Met1','Satisfactory','>=','60')
insert into metric_threshold values('Met1','Needs Improvement','<','60')
insert into metric_threshold values('Met2','In SLA','=','Y')
insert into metric_threshold values('Met2','Out of SLA','=','N')
insert into metric_threshold values('Met3','Mature','=','0')
insert into metric_threshold values('Met3','Needs Improvement','=','1')
insert into metric_threshold values('Met4','In SLA','>','80');
insert into metric_threshold values('Met4','Mature','>=','70');
insert into metric_threshold values('Met4','Satisfactory','<','60');
insert into metric_threshold values('Met4','Needs Improvement','<','50');
create table metric_report
( metric_id varchar(10)
, reporting_date date
, report_values varchar(20)
)
insert into metric_report values('Met1','2020-01-01','72.15')
insert into metric_report values('Met2','2020-01-01','Y')
insert into metric_report values('Met3','2020-01-01','0')
insert into metric_report values('Met1','2020-02-01','80')
insert into metric_report values('Met2','2020-02-01','Y')
insert into metric_report values('Met3','2020-02-01','1')
insert into metric_report values('Met1','2020-03-01','60')
insert into metric_report values('Met2','2020-03-01','Y')
insert into metric_report values('Met3','2020-03-01','1')
insert into metric_report values('Met4','2020-03-01','50');
答案 0 :(得分:1)
这是一种方法-可能不是最漂亮的方法,但是在不更改当前表结构的情况下似乎可以工作。正如我的评论中所提到的那样,这个想法是基于给定vor Met1的评价来评估“实际”阈值,并将所有其他度量作为“简单”标志来处理。可以根据需要进行调整:
WITH cteFlagsOnly AS(
SELECT metric_id, COUNT(DISTINCT symbol) cnt
FROM metric_threshold
WHERE symbol != N'='
GROUP BY metric_id
),
cteNoRange AS(
SELECT DISTINCT metric_id
FROM metric_threshold
WHERE TRY_CONVERT(decimal(19,4), values1) IS NULL
UNION
SELECT DISTINCT t.metric_id
FROM metric_threshold t
LEFT JOIN cteFlagsOnly f ON f.metric_id = t.metric_id
WHERE f.metric_id IS NULL
),
cte AS(
SELECT t.*
,ROW_NUMBER() OVER (PARTITION BY t.metric_id ORDER BY values1 , CASE
WHEN symbol = N'>' THEN 1
WHEN symbol = N'>=' THEN 2
WHEN symbol = N'=' THEN 3
WHEN symbol = N'<=' THEN 4
WHEN symbol = N'<' THEN 5
ELSE 99
END DESC) AS rn
FROM metric_threshold t
LEFT JOIN cteNoRange cn ON cn.metric_id = t.metric_id
WHERE cn.metric_id IS NULL
),
cte2 AS(
SELECT *
,CAST(LAG(values1) OVER (PARTITION BY metric_id ORDER BY rn) AS DECIMAL(19,4)) AS valuesLag
,LAG(symbol) OVER (PARTITION BY metric_id ORDER BY rn) AS symbolLag
,CAST(LEAD(values1) OVER (PARTITION BY metric_id ORDER BY rn) AS DECIMAL(19,4)) AS valuesLead
,LEAD(symbol) OVER (PARTITION BY metric_id ORDER BY rn) AS symbolLead
FROM cte c
),
cteThrashholds AS(
SELECT *
,CASE
WHEN symbol IN (N'<', N'<=') THEN 0.0
WHEN symbol = N'>' THEN CAST(values1 AS decimal(19,4)) + 0.000000001
WHEN symbol = N'>=' THEN CAST(values1 AS decimal(19,4))
ELSE NULL
END AS ValFrom
,CASE
WHEN symbol = N'<' THEN CAST(values1 AS decimal(19,4)) - 0.000000001
WHEN symbol = N'<=' THEN CAST(values1 AS decimal(19,4))
WHEN symbolLead = N'>=' THEN ISNULL(valuesLead - 0.000000001, 9999999.99)
WHEN symbolLead = N'>' THEN ISNULL(valuesLead, 9999999.99)
ELSE ISNULL(valuesLead, 9999999.99)
END AS ValTo
FROM cte2
)
SELECT mr.*, ct.threshold_category
FROM metric_report mr
LEFT JOIN cteNoRange cn ON cn.metric_id = mr.metric_id
LEFT JOIN cteThrashholds ct ON ct.metric_id = mr.metric_id AND mr.report_values BETWEEN ct.ValFrom AND ct.ValTo
WHERE cn.metric_id IS NULL
UNION ALL
SELECT mr.*, ct.threshold_category
FROM metric_report mr
INNER JOIN cteNoRange cn ON cn.metric_id = mr.metric_id
LEFT JOIN metric_threshold ct ON ct.metric_id = mr.metric_id AND mr.report_values = ct.values1
ORDER BY mr.metric_ID
答案 1 :(得分:0)
请仔细阅读sql脚本。
SELECT metric_id,
reporting_date,
report_values,
range
FROM (SELECT mth.metric_id,
rpt.reporting_date,
rpt.report_values,
mth.threshold_category AS Range,
CASE mth.symbol
WHEN '>' THEN
CASE
WHEN Isnumeric(rpt.report_values) <> 0 THEN
CASE
WHEN rpt.report_values > mth.values1 THEN
rpt.report_values + '>=' + mth.values1
ELSE 'N'
END
ELSE 'N'
END
WHEN '>=' THEN
CASE
WHEN Isnumeric(rpt.report_values) <> 0 THEN
CASE
WHEN rpt.report_values >= mth.values1 THEN
rpt.report_values + '>=' + mth.values1
ELSE 'N'
END
ELSE 'N'
END
WHEN '<' THEN
CASE
WHEN Isnumeric(rpt.report_values) <> 0 THEN
CASE
WHEN rpt.report_values < mth.values1 THEN
rpt.report_values + '>=' + mth.values1
ELSE 'N'
END
ELSE 'N'
END
WHEN '=' THEN
CASE
WHEN Isnumeric(rpt.report_values) <> 0 THEN
CASE
WHEN rpt.report_values = mth.values1 THEN
rpt.report_values + '>=' + mth.values1
ELSE 'N'
END
ELSE 'N'
END
END AS Valid
FROM metric_threshold mth,
metric_report rpt) AS x
WHERE x.valid <> 'N'