【问题标题】:MSSQL - Display Column with each data setMSSQL - 显示每个数据集的列
【发布时间】:2023-02-09 02:05:32
【问题描述】:

我正在将数据导出到一个平面文件以导入到 SIEM 中。有没有办法为每个项目显示为“列名=数据”?

SELECT [Description],[MessageDescription]
      ,[CardNumber],[TimeStamp_Server],[SPMDescription][CardHolderID],[FirstName],[MiddleName],[LastName],[CardStatusID],[CardStatusDescription],[Imprint]
      ,[TransactionNumber]
  FROM [DB].[dbo].[Message]
WHERE convert(varchar(10), TimeStamp_Server, 120) = convert(varchar(10), getdate(), 120)

这是它当前在平面文件中的显示方式。

描述、消息描述、卡号、时间戳_服务器、持卡人 ID、名字、中间名、姓氏、CardStatusID、CardStatusDescription、印记、交易号
North Entry,AccessGrantedNoEntry,0,2023-02-08 09:52:19,零售中心C004改装PXL250-2DOOR,,,,,,,527312

我希望每一行都显示为这样

Description = North Entry,MessageDescription = AccessGrantedNoEntry,CardNumber = 0,TimeStamp_Server = 2023-02-08

... 等等。

【问题讨论】:

  • 在提出问题时,您需要提供最小可重现的例子: (1) DDL 和示例数据填充,即 CREATE 表加上 INSERT、T-SQL 语句。 (2) 您需要做什么,即逻辑,以及您尝试在 T-SQL 中实现它。 (3) 基于上面 #1 中示例数据的期望输出。 (4) 您的 SQL Server 版本 (SELECT @@version;)
  • 我认为您正在寻找 UNPIVOT 或 EAV,但如果没有正确的格式,您的问题是不可读的。
  • 问题不在于 SQL。问题是写出文件,我们没有看到任何代码。
  • 此外,如果两个日期时间的日期值相等,则转换为 varchar 是最糟糕的比较方法。
  • 所以你想要在每一行上重现每个列名?这将显着增加文件的大小!只需使用select concat('columnName = ', ColumnName)Columename, ...

标签: sql-server


【解决方案1】:

这是一个附带问题(所以社区维基),但你可以显著地通过像这样更改 WHERE 子句来提高此查询的性能(假设 TimeStamp_ServerDateTime 列):

WHERE TimeStamp_Server >= cast(cast(getdate() as date) as datetime) 
    AND TimeStamp_Server < cast(dateadd(day, 1, cast(getdate() as date)) as datetime)

这在三个方面有帮助:

  1. 由于文化/国际化问题,日期与字符串值之间的转换比我们想象的要慢得多,而且更容易出错。坚持使用 Date 函数和类型将始终表现得更好并且更准确。
  2. 通过将所有修改转移到getdate(),所以TimeStamp_Server保持不变,我们避免需要进行转换表中的每一行.
  3. 通过将所有修改转移到getdate(),使TimeStamp_Server保持不变,我们保留对列可能存在的任何索引的使用。这切入了数据库性能的核心。

【讨论】:

  • 谢谢你的提示。这有助于改善那部分。
【解决方案2】:

未提供最小的可重现示例。所以,我从臀部射击。

请尝试以下概念示例。

恕我直言,JSON 或 XML 输出格式会更可靠。

数据库

-- DDL and sample data population, start
DECLARE @tbl TABLE (id INT PRIMARY KEY, case_date DATE, Product INT);
INSERT INTO @tbl (id, case_date, Product) VALUES
(55, '2022-08-01', 11),
(66, '2022-05-21', 51);
-- DDL and sample data population, end

SELECT t.*
    , result = STUFF(XMLData.query('
        for $x in /root/*
        return concat(", ", local-name($x), "=", $x/text()[1])
        ').value('.', 'VARCHAR(4096)'), 1,2,'')
FROM @tbl AS t
CROSS APPLY (SELECT t.* FOR XML PATH(''), TYPE, ROOT('root')) AS t1(XMLData);

输出

id case_date Product result
55 2022-08-01 11 id=55 , case_date=2022-08-01 , Product=11
66 2022-05-21 51 id=66 , case_date=2022-05-21 , Product=51

【讨论】:

    【解决方案3】:

    使用一些 JSON 和一些字符串操作

    Select replace(
           replace(
           replace(
           replace((Select A.* For JSON Path,Without_Array_Wrapper,INCLUDE_NULL_VALUES  )
                   ,'":"',' = ')
                   ,'","',',')
                   ,'{"','')
                   ,'"}','')
    
    From ( 
           --Your Query Here-- 
         ) A
    

    【讨论】:

      【解决方案4】:

      谢谢 Stu 提供我正在寻找的东西。

      所以你想要在每一行上重现每个列名?这将显着增加文件的大小!只需使用 select concat('columnName = ', ColumnName)Columename, ... – 斯图 3 分钟前

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-17
        • 1970-01-01
        相关资源
        最近更新 更多