Sql 三个表的左连接,显示为动态轴

Sql 三个表的左连接,显示为动态轴,sql,tsql,dynamic,cursor,pivot,Sql,Tsql,Dynamic,Cursor,Pivot,我有三张桌子: payorderType : --------- typeID | TypeName | 1 | accounting | 2 | budget | ---------- step: ---------- StepID | StepName | typeID 1 | payorder | 1 2 | cheque | 1 3 | cheque | 2 ---

我有三张桌子:

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和step创建一个表:

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)与列关联起来?

您应该已经确定了输出结构。拥有可变的产出结构风险不大

但我们要做的是:

  • 使您的结构简单(删除大多数变量)-创建视图(或使用派生表)payorderType+步骤

    -- 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
    
  • 使您的查询更清楚(您的所有字段是否都有空值?。现在您只能使用一个列/变量

  • 现在是关键时刻:

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

    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)
    
  • 抱歉,如果有什么想法是错误的(写在盲板上),但我认为对于指南来说已经足够了。但您应该更喜欢在第2步结束(非静态代码是危险的)。

    可能重复的