我想知道其他人如何处理这种情况......以及如何将“不要重复自己”(DRY)原则应用于这种情况。
我发现自己经常在T-SQL中PIVOTing或编写CASE语句,将Months列为列。我通常有一些字段包括(1)日期字段和(2)值字段。当我通过ASPX页面或Reporting Services将其呈现给用户时,我需要最后最右边的14列才能使用此模式:
[年],[月],[月],[月],[月],[日],[6月],[月],[月],[月],[月],[月] ,[DEC],[总]
年份是int的年份 并且每个其他字段是该月汇总的值字段([Total]除外,它是该年的总值字段)。
我想找到一种可重用的方法来处理这个问题。打开所有建议(T-SQL / ANSI SQL)
答案 0 :(得分:3)
这不完全是你想要的,但我已经做了很多重复的UNPIVOT
,通常,我会用这种代码生成代码,用某种标准化命名并大量使用CTE :
WITH P AS (
SELECT Some Data
,[234] -- These are stats
,[235]
FROM Whatever
)
,FINAL_UNPIVOTED AS (
SELECT Some Data
,[STAT]
FROM P
UNPIVOT (
STAT FOR BASE IN ([234], [235])
) AS unpvt
WHERE STAT <> 0
)
SELECT Some Data
,CONVERT(int, FINAL_UNPIVOTED.[BASE]) AS [BASE]
,FINAL_UNPIVOTED.[STAT]
FROM FINAL_UNPIVOTED
您可以通过检查表或视图并使用以下内容来编码:
DECLARE @sql_unpivot AS varchar(MAX)
SELECT @sql_unpivot = COALESCE(@sql_unpivot + ',', '') + COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'whatever'
并对代码进行模板化:
SET @template = '
WITH P AS (
SELECT Some Data
,{@sql_unpivot}
FROM Whatever
)
,FINAL_UNPIVOTED AS (
SELECT Some Data
,[STAT]
FROM P
UNPIVOT (
STAT FOR BASE IN ({@sql_unpivot})
) AS unpvt
WHERE STAT <> 0
)
SELECT Some Data
,CONVERT(int, FINAL_UNPIVOTED.[BASE]) AS [BASE]
,FINAL_UNPIVOTED.[STAT]
FROM FINAL_UNPIVOTED
'
SET @sql = REPLACE(@template, '{@sql_unpivot}', @sql_unpivot)
等
当然,可以动态运行此代码或创建和SP,您可以换出临时创建的视图或表格,以便为内联内容获取元数据。
请参阅有关表值函数和OUTER APPLY技术的注释。
答案 1 :(得分:1)
现在已经很晚了,我可能会遗漏一些明显的东西,但是每个月有一行的月份表可以帮助你做到这一点吗?
答案 2 :(得分:1)
/* I leave year and month separate so you can use "real" Months or Fiscal Months */
CREATE FUNCTION [dbo].[fn_MonthValueColumns]
(
@year int,
@month int,
@measure int
)
RETURNS TABLE
AS
RETURN
(
SELECT @year as [Year],
CASE WHEN @month = 1 THEN @measure ELSE 0 END AS [Jan],
CASE WHEN @month = 2 THEN @measure ELSE 0 END AS [Feb],
CASE WHEN @month = 3 THEN @measure ELSE 0 END AS [Mar],
CASE WHEN @month = 4 THEN @measure ELSE 0 END AS [Apr],
CASE WHEN @month = 5 THEN @measure ELSE 0 END AS [May],
CASE WHEN @month = 6 THEN @measure ELSE 0 END AS [Jun],
CASE WHEN @month = 7 THEN @measure ELSE 0 END AS [Jul],
CASE WHEN @month = 8 THEN @measure ELSE 0 END AS [Aug],
CASE WHEN @month = 9 THEN @measure ELSE 0 END AS [Sep],
CASE WHEN @month = 10 THEN @measure ELSE 0 END AS [Oct],
CASE WHEN @month = 11 THEN @measure ELSE 0 END AS [Nov],
CASE WHEN @month = 12 THEN @measure ELSE 0 END AS [Dec],
@measure AS [Total]
)
/*
use a group by after your own CROSS APPLY to roll-up SUMs for the last 13 fields.
this function and a CROSS APPLY against 100000 records ran in 3 seconds.
for what I am doing, I can live with that performance.
*/
答案 3 :(得分:0)
使用视图怎么样?
如果您总是使用相同的表/表组,则视图可能有意义。 CAVEAT:当使用大表的一小部分时,请注意这些视图..视图可能会阻止优化器完成它的工作。
答案 4 :(得分:0)