【问题标题】:SQL Server 2008: Joining results of STORED PROCEDURE (dynamic columns) with results of a SELECT statementSQL Server 2008:将 STORED PROCEDURE(动态列)的结果与 SELECT 语句的结果连接起来
【发布时间】:2013-02-11 05:35:58
【问题描述】:

我有由this stored procedure 生成的结果。

我想将这些结果与另一个表中的数据连接起来。我已经看到了创建 临时表 并将其插入其中的各种示例,但是,这并不理想,因为存储过程会返回许多 动态列可调整的。有没有办法动态加入它们?

示例场景:

存储过程返回这个:

EXEC uspGetProductCategories

products_id | products_model | Leather Seats | Heated Seats | Tapedeck | Heater | Hybrid | Sunroof | Cruise Control
===================================================================================================================
100         | Saturn Vue     | N             | N            | Y        | N      | N      | N       | N
200         | Toyota Pruis   | Y             | N            | N        | Y      | Y      | N       | N
300         | Ford Focus     | N             | N            | N        | Y      | N      | N       | Y

我想用一个 SQL 查询加入它,该查询生成如下内容:

SELECT * FROM Products_Detail

products_id | manufacturer | purchaser | pay_type
=================================================
100         | GM           | GREG      | P
200         | TOYT         | SAM       | P
300         | FORD         | GREG      | L

换句话说...

有没有一种无痛的方法可以做到这一点?这是我想要实现的一些伪代码(尽管我知道这不起作用):

SELECT pd.*, sp.* FROM Products_Detail pd
    LEFT JOIN uspGetProductCategories sp ON pd.product_id = sp.product_id

再说一次,我知道你不能这样做,但希望它能描述我正在寻找的逻辑。

期望输出示例

products_id | manufacturer | purchaser | pay_type | products_model | Leather Seats | Heated Seats | Tapedeck | Heater | Hybrid | Sunroof | Cruise Control
=========================================================================================================================================================
100         | GM           | GREG      | P        | Saturn Vue     | N             | N            | Y        | N      | N      | N       | N
200         | TOYT         | SAM       | P        | Toyota Pruis   | Y             | N            | N        | Y      | Y      | N       | N
300         | FORD         | GREG      | L        | Ford Focus     | N             | N            | N        | Y      | N      | N       | Y

【问题讨论】:

  • 必须将SP的结果放入临时表或将JOIN放入SP。
  • 好的,所以没有办法(动态)创建临时表,而不必指定/硬编码列名?
  • 代码必须在 SP 中吗?那么UDF呢?如果您必须使用 SP... 是否可以将此联接添加到存储过程本身中?
  • @MichaelFredrickson 我们中的一些人无法控制 SP 源,但必须添加(甚至“纠正”)我们从它们返回的结果,因此我们不能只添加我们的加入。:-(

标签: sql sql-server stored-procedures join


【解决方案1】:

如果您无法使用来自动态存储过程的数据创建临时表,为什么不直接加入该表:

DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(categories_name) 
                    from Categories
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT ',IsNull(' + QUOTENAME(categories_name)+', ''N'')'+' as '+QUOTENAME(categories_name) 
                    from Categories
                    group by categories_name, categories_id
                    order by categories_id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = '
            select *
            from Products_Detail pd
            left join
            (
              SELECT products_id,
                    products_model,' + @colsNull + ' from 
               (
                  select p.products_id,
                    p.products_model,
                    c.categories_name,
                    ''Y'' flag
                  from products p
                  left join Products_Categories pc
                    on p.products_id = pc.products_id
                  left join Categories c
                    on pc.categories_id = c.categories_id
              ) x
              pivot 
              (
                  max(flag)
                  for categories_name in (' + @cols + ')
              ) p 
            ) p 
              on pd.products_id = p.products_id'

execute(@query)

SQL Fiddle with Demo

【讨论】:

    【解决方案2】:

    如果无法重新组织代码,请尝试使用这种丑陋的解决方案。

    SELECT * INTO #tmp
    FROM OPENROWSET('SQLNCLI', 'server=INSTANCENAME;database=DBNAME;trusted_connection=yes', 'uspGetProductCategories') A
    

    您必须在您的服务器中允许Ad Hoc Distributed Queries

    【讨论】:

      【解决方案3】:

      你可以这样做:

              INSERT aTemptable 
              EXEC yourstoredproc
      

      如果 #t 已定义,但您不能选择进入 #t 并动态创建它。

      【讨论】:

      • 我不需要先用列名/类型定义#aTemptable吗?
      • 抱歉,不小心点击了提交。
      • 在我看来,有一种方法可以创建临时表,其中的列是根据 SP 的输出自动定义的。 (而不是必须手动硬编码/预定义它们)?我的意思是,这基本上是在原始 SP 中完成的。
      【解决方案4】:
      create proc sp_emp18
      (
      @cust_id int,@name varchar(20),@order_id int,@order_date date
      )
      as 
      begin
      select e.cust_id,e.name,d.order_id,d.order_date 
      from 
      customer e inner join orders d on e.cust_id=d.cust_id
      end
      
      exec sp_emp18 101,'ram',99,'2016-07-21'
      

      【讨论】:

      • 虽然此代码可能有助于解决问题,但提供有关 why 和/或 如何 回答问题的额外上下文将显着改善其长期长期价值。请edit你的答案添加一些解释。
      猜你喜欢
      • 1970-01-01
      • 2021-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多