【问题标题】:Dynamic SQL Column Selection动态 SQL 列选择
【发布时间】:2021-10-20 03:02:48
【问题描述】:

我目前有一个表格填充了数天的数据。 这些日期被设置为数据表中的列,因此我需要取消透视表以执行相关查询。

选择所有以2020%开头的列的最简单方法是什么

我使用了以下 Q&A Selecting all columns that start with XXX using a wildcard? 来创建一个包含我需要的所有列的单独表格

SELECT [COLUMN_NAME]
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [TABLE_NAME] = 'Table_Name'
AND [COLUMN_NAME] LIKE '2020%'
GO

但不确定如何使用此辅助表来简化我最初的问题。

【问题讨论】:

  • 阅读prepared statements。在 SQL 中执行它们可能会有些尴尬,因此您可以使用第一个查询的结果在代码中组装查询,而不是全部在 SQL 中完成,但无论哪种方式,您都可以动态编写包含所需特定列的 SQL。
  • 您确定是 SQL Server,而不是 MySQL?因为information_schema 与 MySQL 相关。
  • @MarcusViniciusPompeu information_Schema 是标准 SQL,在 SQL Server 中受支持。此外,使用方括号 ([ /]) 建议使用 SQL Server。在 MySql 中,您将使用 `
  • 您的数据模型似乎已损坏。不要为每个日期使用不同的列,而是为每个日期使用不同的行。
  • @ZoharPeled,你是对的。我的错。

标签: sql sql-server unpivot


【解决方案1】:

您可以对已选择的列使用动态unpivot。以下示例查询可能会对您有所帮助。

DECLARE 
  @sql  NVARCHAR(MAX) = N'',
  @cols NVARCHAR(MAX) = N'';

SELECT @cols += ', ' + QUOTENAME(name)
  FROM sys.columns
  WHERE [object_id] = OBJECT_ID('yourtable')
  AND name LIKE '2020%';

SET @cols =  STUFF(@cols, 1, 1, '')

SELECT @sql = N'SELECT Other_columns, date_columns, val
  FROM 
  (
    SELECT Other_columns, '  + @cols + '
    FROM yourtable
  ) t
  UNPIVOT
  (
    val FOR date_columns IN (' + @cols + ')
  ) up;';
PRINT @sql;
-- EXEC sp_executesql @sql;

请找到最终的数据库小提琴here

【讨论】:

  • 当我尝试运行此代码时,我收到以下错误。知道为什么会这样吗? - ' + STUFF(@cols, 1, 1, ') + ' 附近的语法不正确。
  • @Newbie 很抱歉。我已经更正了一些动态 SQL 错误,请在执行前查看打印的查询是否正常。
  • 抱歉,我似乎仍然无法做到这一点 - 您介意在在线 SQL 服务器平台中创建一个示例
  • @Newbie 我再次更新了答案,动态 SQL 有时会出现问题。请参阅示例here。对这些问题感到抱歉,希望这次它会正常工作。
  • 不幸的是,这并没有给我想要的结果——理想情况下,我想要一列中的日期和另一列中的值。 here
【解决方案2】:

尽管我和 Zohar 不明白为什么存在一个包含每天一列的表格...

对于 MySQL

请考虑一下这个小提琴中的解决方案:https://www.db-fiddle.com/f/7nxjo6hGRsX3Hn8GNqXBuC/0

create table dummy(
  id int,
  --
  relevant_data_01 varchar(255),
  relevant_data_02 varchar(255),
  --
  `20200101` int,
  `20200102` int,
  `20200103` int
);

insert into dummy values(1, 'a', 'b', 1, 2, 3);

select
  concat(
    '
      select *
      from (
    ',
      group_concat(
        concat('
          select
            id, relevant_data_01, relevant_data_02,
            ''', column_name, ''' as date_key,
            `', column_name, '`   as date_value
          from dummy')
        separator
          '
          union all
          '
      ),
    '
      ) d'
  )
into @sql
from INFORMATION_SCHEMA.columns
where
    table_name = 'dummy'
and column_name like '2020%';

PREPARE stmt FROM @sql;
EXECUTE stmt;

对于 SQL Server

编辑解决方案,对于 SQL Server,我提供了另一个小提琴:http://sqlfiddle.com/#!18/f7874c/14

create table dummy(
  id int,
  --
  relevant_data_01 varchar(255),
  relevant_data_02 varchar(255),
  --
  [20200101] int,
  [20200102] int,
  [20200103] int
)

insert into dummy values(1, 'a', 'b', 1, 2, 3)

declare @sql nvarchar(max) = ''

select
  @sql =
    @sql +
    case
      when @sql = '' then ''
                     else char(13) + char(10) + 'union all' + char(13) + char(10)
    end + '
      select
        id, relevant_data_01, relevant_data_02,
        ''' + col.name + ''' as date_key,
        [' + col.name + ']   as date_value
      from dummy
    '
from
  sys.columns col
where
    col.object_id = OBJECT_ID('dummy')
and col.name like '2020%'
  
execute sp_executesql @sql

【讨论】:

  • 我将日期作为列,因为这是最初呈现数据的方式。我的计划是取消透视表(以便将日期作为行)但是,我需要命名我试图找到快捷方式的每一列。我相信上述解决方案在我使用 SQLServer 时在 MySQL 中,因此我收到多个错误
  • @Newbie,我使用 SQL Server 版本编辑了解决方案。很好的发现。
  • 有没有办法将其放入已分配的表中 - 我不断收到以下错误“SELECT INTO 语句不能包含将值分配给变量的 SELECT 语句。”
  • @Newbie,您能否编辑您的问题并发布产生此错误的脚本,“A SELECT INTO ... cannot contain a SELECT... to a variable”?
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多