我有3张桌子。团队,选项,选项团队。
团队拥有一个TeamId,名称
拥有Option拥有OptionId,OptionGroup
OptionTeam拥有TeamId,OptionId,OptionGroup
select a.TeamId, a.Name
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=4) as Option1,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=5) as Option2,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=6) as Option3,
(select count(*) from OptionTeam ot where ot.TeamId=a.TeamId and ot.OptionGroup=11) as Option4
from Team a
我想获得一个团队列表,以及额外的列,这些列指示每个组有多少个选项连接到每个团队。这是通过上面的查询完成的,但是我想用表Option中的OptionGroup值替换4,5,6,11。
它必须是动态的,因为将来可能会有一个新的OptionGroup,并且我希望存储过程能够处理它。
样本数据:
Team
TeamId
1
2
3
选项
OptionId | OptionGroup
11 | 4
12 | 5
13 | 4
14 | 4
15 | 5
期权团队
TeamId | OptionId | OptionGroup
1 | 11 | 4
1 | 13 | 4
2 | 12 | 5
2 | 14 | 4
3 | 15 | 5
我想得到的清单是
TeamId | Group4 (OptionGroup=4) | Group5 (OptionGroup=5)
1 | 2 | 0
2 | 1 | 1
3 | 0 | 1
您将需要一个动态的枢纽来做到这一点。这是存储过程:
CREATE PROC [dbo].[pivotsp]
@query AS NVARCHAR(MAX), -- The query, can also be the name of a table/view.
@on_rows AS NVARCHAR(MAX), -- The columns that will be regular rows.
@on_cols AS NVARCHAR(MAX), -- The columns that are to be pivoted.
@agg_func AS NVARCHAR(257) = N'SUM', -- Aggregate function.
@agg_col AS NVARCHAR(MAX), -- Column to aggregate.
@output AS NVARCHAR(257) = N'', -- Table for results
@debug AS bit = 0 -- 1 for debugging
AS
-- Example usage:
-- exec pivotsp
-- 'select * from vsaleshistory',
-- 'market,marketid,family,familyid,Forecaster,Forecasterid,product,productid',
-- 'month',
-- 'sum',
-- 'ku',
-- '##sales'
-- Input validation
IF @query IS NULL OR @on_rows IS NULL OR @on_cols IS NULL
OR @agg_func IS NULL OR @agg_col IS NULL
BEGIN
RAISERROR('Invalid input parameters.', 16, 1);
RETURN;
END
-- Additional input validation goes here (SQL Injection attempts, etc.)
BEGIN TRY
DECLARE
@sql AS NVARCHAR(MAX),
@cols AS NVARCHAR(MAX),
@newline AS NVARCHAR(2);
SET @newline = NCHAR(13) + NCHAR(10);
-- If input is a valid table or view
-- construct a SELECT statement against it
IF COALESCE(OBJECT_ID(@query, N'U'),
OBJECT_ID(@query, N'V')) IS NOT NULL
SET @query = N'SELECT * FROM ' + @query;
-- Make the query a derived table
SET @query = N'(' + @query + N') AS Query';
-- Handle * input in @agg_col
IF @agg_col = N'*'
SET @agg_col = N'1';
-- Construct column list
SET @sql =
N'SET @result = ' + @newline +
N' STUFF(' + @newline +
N' (SELECT N'','' + quotename( '
+ 'CAST(pivot_col AS sysname)' +
+ ') AS [text()]' + @newline +
N' FROM (SELECT DISTINCT('
+ @on_cols + N') AS pivot_col' + @newline +
N' FROM' + @query + N') AS DistinctCols' + @newline +
N' ORDER BY pivot_col' + @newline +
N' FOR XML PATH(''''))' + @newline +
N' ,1, 1, N'''');'
IF @debug = 1
PRINT @sql
EXEC sp_executesql
@stmt = @sql,
@params = N'@result AS NVARCHAR(MAX) OUTPUT',
@result = @cols OUTPUT;
IF @debug = 1
PRINT @cols
-- Create the PIVOT query
IF @output = N''
begin
SET @sql =
N'SELECT *' + @newline +
N'FROM (SELECT '
+ @on_rows
+ N', ' + @on_cols + N' AS pivot_col'
+ N', ' + @agg_col + N' AS agg_col' + @newline +
N' FROM ' + @query + N')' +
+ N' AS PivotInput' + @newline +
N' PIVOT(' + @agg_func + N'(agg_col)' + @newline +
N' FOR pivot_col IN(' + @cols + N')) AS PivotOutput;'
end
ELSE
begin
set @sql = 'IF EXISTS (SELECT * FROM tempdb.sys.objects WHERE ' +
'name = ''' + @output + ''' AND type = N''U'') DROP TABLE tempdb.' + @output
EXEC sp_executesql @sql;
SET @sql =
N'SELECT * INTO ' + @output + @newline +
N'FROM (SELECT '
+ @on_rows
+ N', ' + @on_cols + N' AS pivot_col'
+ N', ' + @agg_col + N' AS agg_col' + @newline +
N' FROM ' + @query + N')' +
+ N' AS PivotInput' + @newline +
N' PIVOT(' + @agg_func + N'(agg_col)' + @newline +
N' FOR pivot_col IN(' + @cols + N')) AS PivotOutput;'
end
IF @debug = 1
PRINT @sql
EXEC sp_executesql @sql;
END TRY
BEGIN CATCH
DECLARE
@error_message AS NVARCHAR(2047),
@error_severity AS INT,
@error_state AS INT;
SET @error_message = ERROR_MESSAGE();
SET @error_severity = ERROR_SEVERITY();
SET @error_state = ERROR_STATE();
RAISERROR(@error_message, @error_severity, @error_state);
RETURN;
END CATCH
这样一来,就很容易在可变数量的列上进行数据透视:
EXEC pivotsp
'SELECT TeamID, OptionGroup, OptionID AS Options FROM OptionTeam',
'Teamid', -- Row headers
'optiongroup', -- item to aggregate
'count', -- aggregation function
'optiongroup', -- Column header
'##temp' -- output table name
SELECT * FROM ##temp
结果:
Teamid 4 5
1 2 0
2 1 1
3 0 1
问题内容: 我知道使用准备好的语句有助于避免sql- injection。我的问题是,准备好的语句通常是非常静态的。我有一个问题,我在哪里在运行时根据用户输入建立sql查询的子句。根据填充的输入字段,我必须将相应的语句添加到where子句中。如何通过准备好的语句实现这一目标? 问题答案: 我猜您可以根据要查询的列来动态构建准备好的语句,即使用StringBuffer和循环根据所需的列来构建它们。
问题内容: 在C语言中非常常见:像这样入侵“空if语句”: 它在Python中工作吗?我的意思是,我们可以通过使用它来提高应用程序的性能吗?我也想知道为什么。 问题答案: 如果“ if”中没有其他情况,则性能会得到改善,因为字节码不会将执行传递给“ if”情况。 这是一些功能和输出 以下示例应用程序: 分解为: 以下 分解为:
我正在用android创建一款纸牌游戏(21点)。前两张卡是easy card1和card2,但是我想按一下“点击我”按钮,发一张新卡,并将其分配给card3、card4等。有没有任何方法可以做到这一点,而无需创建所需的最大变量数,并使用if-then语句检查它们是否被分配了值?
我正在将java脚本移动到dart,在java脚本中我创建了动态变量,例如 我怎么能用飞镖呢?
问题内容: 我在使用primefaces树实现实现动态树结构时遇到了一些麻烦。在primeface提供的展示柜中,代码的结构如下所示。但是,这是非常静态的。我试图弄清楚如何处理从数据库中获取的数据,在编译时树的深度是未知的。 我以为我可能需要某种递归方法来实现此目的,但我无法完全理解实现的样子。 有什么想法吗? 以下是primefaces的示例代码 问题答案:
对于一个开关案例,假设我有5个不同的案例,其中三个共享一个我不想重复的共同动作。以下代码完美地说明了我想要实现的目标(但在切换中): 我能把它写成一个优雅的开关盒吗?我目前的解决方案如下所示: