左边连接3个表并显示为动态轴

时间:2017-01-01 04:19:10

标签: sql tsql dynamic cursor pivot

我有3张桌子:

payorderType : 
---------
typeID | TypeName   |
   1   | accounting |
   2   | budget     |
----------          
step:
----------
 StepID | StepName   | typeID
   1   | payorder   |   1
   2   | cheque     |   1
   3   | cheque     |   2

----------
user:
----------
  userID | StepName   | StepID
   7878  | payorder   |   1
   4547  | cheque     |   2
   6538  | cheque     |   1


----------

我想创建一个表,其中行和列中的用户包含step和payorderType的concat。同如下:

           users | accounting_payorder | accounting_cheque | budget_cheque |
           7878  |          1          |        0          |       0       |
           4547  |          0          |        1          |       0       |
           6538  |          0          |        1          |       0       |

我的问题是:如果我不知道payorderType行数和步行数,我该怎么写呢? 我的剧本在这里: 首先,我在游标中为concat payorderType创建一个表,然后执行步骤:

CREATE PROC sp_payOrderType

AS

BEGIN

    DECLARE a CURSOR

    FOR SELECT DISTINCT p.TypeName,s.StepName 
    FROM 
        dbo.PayOrderType p LEFT JOIN 
        dbo.vStep s ON s.TypeID = p.TypeID
    FOR READ ONLY 

    DECLARE @payOrderType NVARCHAR(50),@stepName NVARCHAR(50)
    DECLARE @SQL NVARCHAR(MAX)=''

    OPEN a
    FETCH NEXT FROM a INTO @payOrderType, @stepName 
    WHILE @@FETCH_STATUS=0

    BEGIN
        DECLARE @b VARCHAR(max), @b2 VARCHAR(max)

        SELECT @b  =  ISNULL(@b ,'') +'['+ ISNULL(@payOrderType ,'')+ '____'+ISNULL(@stepName ,'')+ ']'+ ' NVARCHAR(1000) ,'

        FETCH NEXT FROM a INTO @payOrderType,@stepName    
    END

    CLOSE a
    DEALLOCATE a 
    SELECT @SQL  = 'ALTER table AA(' + SUBSTRING(@b,1, LEN(@b)-1) + ')'
    SELECT @SQL  

END

但我不知道我应该如何将行(userID)与列相关联?

1 个答案:

答案 0 :(得分:0)

您应该已经确定了输出结构。具有可变输出结构的风险很小。

但是我们走了:

  1. 使您的结构简单(删除大部分变量) - 创建视图(或使用派生表)payorderType + step

    -- should be inner join probably instead of left join
    -- if you use left join you have to isnull s.StepName
    SELECT 
        u.userID, 
        s.StepID, 
        p.TypeName, 
        s.StepName, 
        p.TypeName + '_' + s.StepName StepType, 
        -- Your column can be like `coalesce(p.TypeName + '_' + s.StepName, p.TypeName, s.StepName) StepType` for left joins
        1 Point
    FROM dbo.PayOrderType p 
    INNER JOIN dbo.vStep s ON s.TypeID = p.TypeID 
    INNER JOIN dbo.user u ON u.StepID = s.StepID
    
  2. 让您的查询更清晰(您的所有字段都可以包含空值吗?现在您只能处理一个列/变量。

    1. 现在是时间轴:

      SELECT 
          userID,
          [accounting_payorder], 
          [accounting_cheque], 
          [budget_cheque]
      FROM newview v
      PIVOT(MAX(point) FOR StepType in ([accounting_payorder], [accounting_cheque], [budget_cheque])
      
    2. 如果必要,您可以使用动态查询:

      declare @header varchar(max),
              @columns varchar(max)
      
      select @header = coalesce(@header + ', ', '') + 'isnull(''' + StepType + ''', 0) ' + '[' + StepType + ']',
             @columns = coalesce(@columns + ', ', '') + '[' + StepType + ']'
      from newview
      group by StepType
      
      declare @sqlpvt varchar(4000) -- limited by lenght of exec statement
      set @sqlpvt = 'select userID, $HEADER FROM newview v PIVOT(MAX(point) FOR StepType in ($COLUMNS)'
      -- replace pseudovariables
      set @sqlpvt = replace(@sqlpvt, '$HEADER', @header)
      set @sqlpvt = replace(@sqlpvt, '$COLUMNS', @columns)
      
      print @sqlpvt
      exec (@sqlpvt)
      
    3. 对不起,如果有些想法是错误的(盲目写入),但我认为对于指南来说已经足够了。但是你应该更喜欢在第2步结束(非静态代码很危险)。