英文:
T-SQL - Can I do this without hard-coding the Case Statement
问题
以下是您要翻译的内容:
"I have other SQL that results in a query which I stored in a table for testing and sanitizing the data. The following query accomplishes what I want to do for this specific case (i.e. continue to have 3 rows of data with the PiValue filled in properly from other columns, based on the value of the PiTag and or the FieldName column). I will be sending CONTRACT_DAY, PiTag and PiValue to a timeseries database called PI (PiSystem) using other tools.
Note that my case statement is hard-coding the values in the FieldName and PiTag column. So if they ever added a new field, I would have to change, and redeploy my query. So I'm wondering if there is a clever way in T-SQL to do this without the "case" logic that I have provided. I was thinking maybe "pivot" could help."
"CREATE TABLE [dbo].[NealTempDemo](
[METER_IDNUM] nvarchar NOT NULL,
[CONTRACT_DAY] [smalldatetime] NOT NULL,
[VOLUME] [float] NULL,
[HEATING_VALUE] [float] NULL,
[ENERGY] [float] NULL,
[PiTag] nvarchar NULL,
[FieldName] nvarchar NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_Volume', N'VOLUME')
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_Energy', N'ENERGY')
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_GHV', N'HEATING_VALUE')
GO"
英文:
I have other SQL that results in a query which I stored in a table for testing and sanitizing the data. The following query accomplishes what I want to do for this specific case (i.e. continue to have 3 rows of data with the PiValue filled in properly from other columns, based on the value of the PiTag and or the FieldName column). I will be sending CONTRACT_DAY, PiTag and PiValue to a timeseries database called PI (PiSystem) using other tools.
Note that my case statement is hard-coding the values in the FieldName and PiTag column. So if they ever added a new field, I would have to change, and redeploy my query. So I'm wondering if there is a clever way in T-SQL to do this without then "case" logic that I have provided. I was thinking maybe "pivot" could help.
SELECT METER_IDNUM
,CONTRACT_DAY
,VOLUME
,HEATING_VALUE
,ENERGY
,FieldName
,PiTag
,case when PiTag = 'ABC-Raw_Volume' then VOLUME
when PiTag = 'ABC-Raw_Energy' then ENERGY
when PiTag = 'ABC-Raw_GHV' then HEATING_VALUE
else 0
end as PiValue
FROM [dbo].[NealTempDemo]
I put it on SQLFiddle here: http://sqlfiddle.com/#!18/94803/1
Create data SQL is:
CREATE TABLE [dbo].[NealTempDemo](
[METER_IDNUM] [nvarchar](20) NOT NULL,
[CONTRACT_DAY] [smalldatetime] NOT NULL,
[VOLUME] [float] NULL,
[HEATING_VALUE] [float] NULL,
[ENERGY] [float] NULL,
[PiTag] [nvarchar](max) NULL,
[FieldName] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_Volume', N'VOLUME')
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_Energy', N'ENERGY')
GO
INSERT [dbo].[NealTempDemo] ([METER_IDNUM], [CONTRACT_DAY], [VOLUME], [HEATING_VALUE], [ENERGY], [PiTag], [FieldName]) VALUES (N'12345', CAST(N'2023-01-01T00:00:00' AS SmallDateTime), 2325498, 1009.3034147640643, 2347136, N'ABC-Raw_GHV', N'HEATING_VALUE')
GO
答案1
得分: 3
以下将会将整个当前行转换为XML,然后使用FieldName
值来选择所需的列元素并提取该值。
SELECT METER_IDNUM
,CONTRACT_DAY
,VOLUME
,HEATING_VALUE
,ENERGY
,FieldName
,PiTag
,X.XML.value('(*[local-name()=sql:column("D.FieldName")]/text())[1]', 'float') AS PiValue
--,X.XML
FROM NealTempDemo D
CROSS APPLY (
SELECT D.*
FOR XML PATH(''), TYPE
) AS X(XML);
上述假设所有选择的值都可以转换为FLOAT
。
结果:
METER_IDNUM | CONTRACT_DAY | VOLUME | HEATING_VALUE | ENERGY | FieldName | PiTag | PiValue |
---|---|---|---|---|---|---|---|
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | VOLUME | ABC-Raw_Volume | 2325498 |
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | ENERGY | ABC-Raw_Energy | 2347136 |
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | HEATING_VALUE | ABC-Raw_GHV | 1009.30341476406 |
请参考这个db<>fiddle以获取一个工作演示。
注意 请注意,这种方法可能会给您的查询增加昂贵的开销,特别是如果您的数据包含"数十个其他列"。如果您的数据来自多个不同的源并进行连接,您可能希望在靠近数据源的位置应用XML操作,以减少数据膨胀。
英文:
The following will convert the entire current row to XML and then use the FieldName
value to select the desired column element to extract the value.
SELECT METER_IDNUM
,CONTRACT_DAY
,VOLUME
,HEATING_VALUE
,ENERGY
,FieldName
,PiTag
,X.XML.value('(*[local-name()=sql:column("D.FieldName")]/text())[1]', 'float') AS PiValue
--,X.XML
FROM NealTempDemo D
CROSS APPLY (
SELECT D.*
FOR XML PATH(''), TYPE
) AS X(XML);
The above assumes that all selected values are convertible to FLOAT
.
Results:
METER_IDNUM | CONTRACT_DAY | VOLUME | HEATING_VALUE | ENERGY | FieldName | PiTag | PiValue |
---|---|---|---|---|---|---|---|
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | VOLUME | ABC-Raw_Volume | 2325498 |
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | ENERGY | ABC-Raw_Energy | 2347136 |
12345 | 2023-01-01 00:00 | 2325498 | 1009.30341476406 | 2347136 | HEATING_VALUE | ABC-Raw_GHV | 1009.30341476406 |
See this db<>fiddle for a working demo.
Caution Just be aware that this approach may add costly overhead to your query - especially if your data contains "dozens of other columns". If your data is coming from several different sources joined together, you might want to look at applying the XML operation at a point closer to the source where data bloat isn't as bad.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论