T-SQL – 我可以在不硬编码 Case 语句的情况下实现这个吗

huangapple go评论92阅读模式
英文:

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.

T-SQL – 我可以在不硬编码 Case 语句的情况下实现这个吗

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(&#39;(*[local-name()=sql:column(&quot;D.FieldName&quot;)]/text())[1]&#39;, &#39;float&#39;) AS PiValue
      --,X.XML
FROM NealTempDemo D
CROSS APPLY (
    SELECT D.*
    FOR XML PATH(&#39;&#39;), 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.

huangapple
  • 本文由 发表于 2023年2月10日 04:43:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404242.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定