我已经使用基本的t-sql作为工作的一部分已经有一段时间但是从来没有真正花费太多时间来发展我的技能组合并且将自己归类为初学者 - 中等。我有一个任务,我有特定体育比赛的数据以及每个月的数字数据,例如
Competition, StartDate, EndDate, Aug_2017_Total, September_2017_Total,October_2017_Total
English Premier Leage, 2017-08-01,2018-07-01, 20, 30, 45
我需要基本上创建一个总列,如果数字数据的列标题,例如Aug_2017_otal在开始日期和结束日期之间,对内容进行求和,例如Aug_2017_Total + September_2017Total等。
伪代码类似
sum(if columnanme like Total and columname between start date and end date)
但是对于我的生活,我找不到以这种方式引用列标题的方法。我简要地研究了col_name
和sysobjects
,但他们似乎没有给我我正在寻找的功能......
我想我错过了一些明显的东西......
答案 0 :(得分:0)
我希望以下内容有助于说明为什么需要更改存储数据的方式。下面我使用了3个查询,这些查询全部联合在一起以生成更加规范化的结构。使用这种方法,您可以添加下个月的数据,而无需添加列,也可以更轻松地对数据进行求和。
您在下面看到的数据有很多关于您的数据的假设,仅作为指导。
MS SQL Server 2014架构设置:
CREATE TABLE Table1
([Competition] varchar(21), [StartDate] date, [EndDate] date, [Aug_2017_Total] int, [September_2017_Total] int, [October_2017_Total] int)
;
INSERT INTO Table1
([Competition], [StartDate], [EndDate], [Aug_2017_Total], [September_2017_Total], [October_2017_Total])
VALUES
('English Premier Leage', '2017-08-01', '2017-07-01', 20, 30, 45),
('English Premier Leage', '2017-09-01', '2017-09-01', 20, 30, 45),
('English Premier Leage', '2017-10-01', '2017-10-01', 20, 30, 45)
;
查询1 :
select
Competition
, startdate
, concat(datename(month,startdate) + '_', year(startdate) ) MonthLabel
, MonthValue
from (
select Competition, StartDate, Aug_2017_Total as MonthValue
from table1
where StartDate = '20170801'
UNION ALL
select Competition, StartDate, September_2017_Total as MonthValue
from table1
where StartDate = '20170901'
UNION ALL
select Competition, StartDate, October_2017_Total as MonthValue
from table1
where StartDate = '20171001'
) unpiv
<强> Results 强>:
| Competition | startdate | MonthLabel | MonthValue |
|-----------------------|------------|----------------|------------|
| English Premier Leage | 2017-08-01 | August_2017 | 20 |
| English Premier Leage | 2017-09-01 | September_2017 | 30 |
| English Premier Leage | 2017-10-01 | October_2017 | 45 |
查询2 :
select
Competition
, SUM(MonthValue)
from (
select Competition, StartDate, Aug_2017_Total as MonthValue
from table1
where StartDate = '20170801'
UNION ALL
select Competition, StartDate, September_2017_Total as MonthValue
from table1
where StartDate = '20170901'
UNION ALL
select Competition, StartDate, October_2017_Total as MonthValue
from table1
where StartDate = '20171001'
) unpiv
where startdate >= '20170801'
and startdate < '20180801'
group by
Competition
<强> Results 强>:
| Competition | |
|-----------------------|----|
| English Premier Leage | 95 |
答案 1 :(得分:0)
您可能还想考虑 UNPIVOT 。它可以为您提供一个位置来添加新列,而不是每次发生更改时都编写整个select语句。
_Months CTE用于匹配应与总列匹配的月份。如果您坚持使用命名约定 {MMM [M]} _ {yyyy} _Total ,那么这应该继续适合您。
_Results CTE可供您进一步查询以获取您感兴趣的输出。
设置测试数据:
IF (OBJECT_ID('dbo.Scores') IS NOT NULL) DROP TABLE dbo.Scores;
GO
CREATE TABLE dbo.Scores (
Competition varchar(50),
StartDate date,
EndDate date,
Aug_2017_Total int,
September_2017_Total int,
October_2017_Total int
);
INSERT Scores
(Competition, StartDate, EndDate, Aug_2017_Total, September_2017_Total, October_2017_Total)
VALUES
('English Premier League', '2017-08-01', '2017-08-31', 20, 30, 45),
('English Premier League', '2017-09-01', '2017-09-30', 20, 30, 45),
('English Premier League', '2017-10-01', '2017-10-30', 20, 30, 45),
('Serie A', '2017-08-01', '2017-08-31', 20, 30, 45),
('Serie A', '2017-09-01', '2017-09-30', 20, 30, 45),
('Serie A', '2017-10-01', '2017-10-30', 20, 30, 45),
('La Liga', '2017-08-01', '2017-08-31', 20, 30, 45),
('La Liga', '2017-09-01', '2017-09-30', 20, 30, 45),
('La Liga', '2017-10-01', '2017-10-30', 20, 30, 45),
('Bundesliga', '2017-08-01', '2017-08-31', 20, 30, 45),
('Bundesliga', '2017-09-01', '2017-09-30', 20, 30, 45),
('Bundesliga', '2017-10-01', '2017-10-30', 20, 30, 45),
('Major League Soccer', '2017-08-01', '2017-08-31', 20, 30, 45),
('Major League Soccer', '2017-09-01', '2017-09-30', 20, 30, 45),
('Major League Soccer', '2017-10-01', '2017-10-30', 20, 30, 45);
GO
<强>查询强>
WITH _Months AS (
SELECT 1 [MonthNumber], 'January' [MonthFullName]
UNION ALL SELECT 2 [MonthNumber], 'February' [MonthFullName]
UNION ALL SELECT 3 [MonthNumber], 'March' [MonthFullName]
UNION ALL SELECT 4 [MonthNumber], 'April' [MonthFullName]
UNION ALL SELECT 5 [MonthNumber], 'May' [MonthFullName]
UNION ALL SELECT 6 [MonthNumber], 'June' [MonthFullName]
UNION ALL SELECT 7 [MonthNumber], 'July' [MonthFullName]
UNION ALL SELECT 8 [MonthNumber], 'August' [MonthFullName]
UNION ALL SELECT 9 [MonthNumber], 'September' [MonthFullName]
UNION ALL SELECT 10 [MonthNumber], 'October' [MonthFullName]
UNION ALL SELECT 11 [MonthNumber], 'November' [MonthFullName]
UNION ALL SELECT 12 [MonthNumber], 'December' [MonthFullName]
),
_Results AS (
SELECT
Competition,
StartDate,
EndDate,
X.Points -- ... Points FOR ...
-- X.ColumnName, -- ... FOR ColumnName IN ...
FROM
Scores S
UNPIVOT(
Points FOR ColumnName IN (
Aug_2017_Total,
September_2017_Total,
October_2017_Total
-- add new columns here as the table structure changes
)
) X
INNER JOIN _Months M ON M.MonthFullName LIKE LEFT(X.ColumnName, CHARINDEX('_', X.ColumnName) - 1) + '%'
WHERE
M.MonthNumber = MONTH(StartDate)
AND CONVERT(int, SUBSTRING(X.ColumnName, CHARINDEX('_', X.ColumnName) + 1, 4)) = YEAR(StartDate)
)
SELECT
*
FROM
_Results R