2

我有 2 张桌子

##tblReports - temporary table

Books| GroupId | Category | 01-01-2014 | 02-01-2014 | ..etc
----------+------------+--------------------------
100  | 1       | Limit    | 700         | 0
100  | 1       | Exp      | 70          | 0
100  | 1       | Balance  | 630         | 0
200  | 1       | Limit    | 0           | 900
200  | 1       | Exp      | 0           | 100
200  | 1       | Balance  | 0           | 800


tblLimits -user table

GroupId | 100BooksLimit | 200BooksLimit
----------+------------+---------------
1       | 700           | 900
2       | 7             | 10

期望的输出

Books| GroupId | Category | 01-01-2014 | 02-01-2014
----------+------------+--------------------------
100  | 1       | Limit    | 700         | 700
100  | 1       | Exp      | 70          | 0
100  | 1       | Balance  | 630         | 700
200  | 1       | Limit    | 900         | 900
200  | 1       | Exp      | 0           | 100
200  | 1       | Balance  | 900         | 800

从##tblReports 开始的第 3 列是动态的。你能帮我如何更新它吗?

基本上:

  1. 查找所有值为 0 的列
  2. 使用 GroupId 和 Books 在 tblLimits 表中搜索其限制。
  3. 获取限制并更新“限制”和“平衡”行

我尝试使用动态查询,但无法使其工作。请帮我

*我知道表格的设计并不理想,并遵循最佳实践,因为这是我需要遵循的客户要求。这是一张临时表,在这张表之前发生了很多事情(多个联接、透视和取消透视)

显示的表格是简化的,并不完全复制实际的表格。谢谢!

4

1 回答 1

1
-- Create temp tables and sample data
CREATE TABLE ##tblReports (books INT, groupid INT, category VARCHAR(25), [01-01-2014] INT, [02-01-2014] INT)
INSERT INTO ##tblReports VALUES (100, 1, 'Limit', 700, 0), (100, 1, 'Exp', 70, 0), (100, 1, 'Balance', 630, 0),
(200, 1, 'Limit', 0, 900), (200, 1, 'Exp', 0, 100), (200, 1, 'Balance', 0, 800)

CREATE TABLE ##tblLimits (groupid INT, [100bookslimit] INT, [200bookslimit] INT)
INSERT INTO ##tblLimits VALUES (1, 700, 900), (2, 7, 10)

-- Unpivot ##tblLimits in a CTE (see footnote for what this outputs)
DECLARE @sql NVARCHAR(MAX)
SELECT @sql = '
;WITH cte_unpivot AS
(
    SELECT groupid, val, CAST(REPLACE(col, ''bookslimit'', '''') AS INT) AS books
    FROM ##tblLimits
    UNPIVOT (val FOR col IN ('

-- Are the columns in ##tblLimits dynamic (other than groupid)? If so, get their 
-- names from tempdb.sys.columns metadata.  
SELECT @sql += QUOTENAME(name) + ',' -- [Column],
FROM tempdb.sys.columns 
WHERE [object_id] = OBJECT_ID(N'tempdb..##tblLimits') AND name <> 'groupid'

-- Delete trailing comma
SELECT @sql = SUBSTRING(@sql, 1, LEN(@sql) - 1) 

SELECT @sql +=  '))AS u
)
SELECT t.books, t.groupid, category, 
'

-- Get ##tblReports column names from tempdb.sys.columns metadata.
SELECT @sql += '
    CASE WHEN ' + QUOTENAME(name) + ' = 0 AND t.category IN (''Limit'', ''Balance'') 
        THEN c.val ELSE t.' + QUOTENAME(name) + ' END AS ' + QUOTENAME(name) + ','
FROM tempdb.sys.columns 
WHERE [object_id] = OBJECT_ID(N'tempdb..##tblReports') AND name NOT IN ('books', 'groupid', 'category')

-- Delete trailing comma again
SELECT @sql = SUBSTRING(@sql, 1, LEN(@sql) - 1) 

SELECT @sql += '
FROM ##tblReports t
LEFT JOIN cte_unpivot c ON t.books = c.books AND t.groupid = c.groupid
'

EXEC sp_executesql @sql

回报:

books   groupid category    01-01-2014  02-01-2014
100     1       Limit       700         700
100     1       Exp         70          0
100     1       Balance     630         700
200     1       Limit       900         900
200     1       Exp         0           100
200     1       Balance     900         800

关键是将##tblLimits 转换为这种格式,以便您可以轻松地将其加入##tblReports:

groupid val books
1       700 100
1       900 200
2       7   100
2       10  200

这是它生成的 SQL(但已格式化):

;WITH cte_unpivot 
     AS (SELECT groupid, 
                val, 
                Cast(Replace(col, 'bookslimit', '') AS INT) AS books 
         FROM   ##tbllimits 
                UNPIVOT (val 
                        FOR col IN ([100bookslimit], 
                                    [200bookslimit]))AS u) 
SELECT t.books, 
       t.groupid, 
       category, 
       CASE 
         WHEN [01-01-2014] = 0 
              AND t.category IN ( 'Limit', 'Balance' ) THEN c.val 
         ELSE t.[01-01-2014] 
       END AS [01-01-2014], 
       CASE 
         WHEN [02-01-2014] = 0 
              AND t.category IN ( 'Limit', 'Balance' ) THEN c.val 
         ELSE t.[02-01-2014] 
       END AS [02-01-2014] 
FROM   ##tblreports t 
       LEFT JOIN cte_unpivot c 
              ON t.books = c.books 
                 AND t.groupid = c.groupid 
于 2018-10-28T08:09:34.933 回答