我有一个名为WorkDetails的表,它具有以下列名: ChargeCode ,, EndShiftDate,A1,B1,C1,A2,B2,C2,......,A10,B10,C10 所有列A,B和C都具有数值,表示特定日期的任务花费的小时数。 我能写一个像这样的插入语句:
insert into myTable
(chargeCode, EndShiftCode, [hours])
select chargeCode, DATEADD(dd, -10, EndShiftCode), sum(A1)
FROM WorkDetails
Where ChargeCode in (1,2,5)
group by chargeCode, EndShiftCode, A1
insert into myTable
(chargeCode, EndShiftCode, [hours])
select chargeCode, DATEADD(dd, -9, EndShiftCode), sum(A2)
FROM WorkDetails
Where ChargeCode in (1,2,5)
group by chargeCode, EndShiftCode, A2
问题是我必须写30次才能将列名从A1更改为A10,B1更改为B10,C1更改为C10。
有没有更好的方法来编写insert语句,我可以通过循环遍历以A,然后是B和C开头的所有列来将列名指定为“Where ColName like'A%'”? p>
谢谢!
答案 0 :(得分:2)
您不需要动态SQL。您可以从不同的(也可以是基于集合的)方法处理问题。只需将查询交叉连接到数字/计数表(或通过CTE创建一个内联)以获取列数(例如,在您的情况下为TOP(30)
),然后使用CASE语句选择所需的列。数字表/ CTE中的每个单独值将表示一行等同于您的一个硬编码查询。由于每一行都是一个不同的"查询",每一行都可以从不同的A,B或C列中提取。
测试设置:
SET NOCOUNT ON;
IF (OBJECT_ID(N'tempdb..#Bob') IS NOT NULL)
BEGIN
DROP TABLE #Bob;
END;
CREATE TABLE #Bob (
ChargeCode INT, EndShiftDate DATETIME, A1 INT, B1 INT, C1 INT,
A2 INT, B2 INT, C2 INT, A3 INT, B3 INT, C3 INT, A4 INT, B4 INT, C4 INT,
A5 INT, B5 INT, C5 INT, A6 INT, B6 INT, C6 INT, A7 INT, B7 INT, C7 INT,
A8 INT, B8 INT, C8 INT, A9 INT, B9 INT, C9 INT, A10 INT, B10 INT, C10 INT
);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (1, '2015-01-05', 1);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (1, '2015-01-05', 5);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (2, '2015-01-05', 3);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (2, '2015-01-05', 56);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (2, '2015-01-17', 300);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (2, '2015-01-17', 6);
INSERT INTO #Bob (ChargeCode, EndShiftDate, A1) VALUES (7, '2015-01-17', 10000);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (10, '2015-01-05', 11);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (10, '2015-01-05', 15);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (50, '2015-01-05', 13);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (50, '2015-01-05', 156);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (50, '2015-01-17', 1300);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (50, '2015-01-17', 16);
INSERT INTO #Bob (ChargeCode, EndShiftDate, B1) VALUES (77, '2015-01-17', 100000);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (200, '2015-02-05', 51);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (200, '2015-02-05', 55);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (100, '2015-02-05', 53);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (100, '2015-02-05', 556);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (100, '2015-02-17', 5300);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (100, '2015-02-17', 56);
INSERT INTO #Bob (ChargeCode, EndShiftDate, C2) VALUES (111, '2015-02-17', 1000000);
SELECT * FROM #Bob;
单个非动态SQL查询:
;WITH nums AS
(
SELECT TOP (6) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [TheNum]
FROM [sys].[objects]
), agg AS
(
SELECT b.ChargeCode,
DATEADD(DAY, (CEILING(nums.TheNum / 3.0) - 11), b.EndShiftDate) AS [EndShiftDate],
SUM(
CASE nums.TheNum
WHEN 1 THEN b.A1
WHEN 2 THEN b.B1
WHEN 3 THEN b.C1
WHEN 4 THEN b.A2
WHEN 5 THEN b.B2
WHEN 6 THEN b.C2
--repeat for 7, 8, 9 to be [ABC]3; 10, 11, 12 to be [ABC]4; and so on...
END
) AS [Hours]
FROM #Bob b
CROSS JOIN nums
WHERE 1 = CASE
WHEN nums.TheNum % 3 = 1 AND chargeCode IN (1, 2, 5) THEN 1 -- A
WHEN nums.TheNum % 3 = 2 AND chargeCode IN (10, 50, 70) THEN 1 -- B
WHEN nums.TheNum % 3 = 0 AND chargeCode IN (100, 200, 500) THEN 1 -- C
END
GROUP BY b.chargeCode, DATEADD(DAY, (CEILING(nums.TheNum / 3.0) - 11), b.EndShiftDate)
)
-- INSERT INTO myTable (ChargeCode, [EndShiftDate], [Hours])
SELECT ChargeCode, [EndShiftDate], [Hours]
FROM agg
WHERE agg.[Hours] IS NOT NULL;
结果(INSERT
已注释掉):
ChargeCode EndShiftDate Hours
---------- ------------ -----
1 2014-12-26 00:00:00.000 6
2 2014-12-26 00:00:00.000 59
10 2014-12-26 00:00:00.000 26
50 2014-12-26 00:00:00.000 169
2 2015-01-07 00:00:00.000 306
50 2015-01-07 00:00:00.000 1316
100 2015-01-27 00:00:00.000 609
200 2015-01-27 00:00:00.000 106
100 2015-02-08 00:00:00.000 5356
答案 1 :(得分:1)
您可以使用动态sql,如下所示:
declare @sql nvarchar(max) = ''
declare @column varchar(max)
declare cur cursor for select name from sys.columns where object_name(object_id) = 'WorkDetails' and name not in ('chargeCode', 'EndShiftCode')
open cur
fetch next from cur into @column;
while @@fetch_status = 0
begin
set @sql = @sql + 'insert into myTable(chargeCode, EndShiftCode, [hours])' + char(13) + char(10)
+ 'select chargeCode, DATEADD(dd, -9, EndShiftCode), sum({0}) FROM WorkDetails Where ChargeCode in (1,2,5) group by chargeCode, EndShiftCode, {0}'
set @sql = replace(@sql, '{0}', @column)
fetch next from cur;
end
select @sql
close cur
deallocate cur
答案 2 :(得分:0)
您可以使用information_schema最大限度地减少手动编写查询的重复工作。我更喜欢在动态查询上手动编写查询。
即
declare @var varchar(8000) = ' insert into .... WHERE ... GROUP BY '
declare @resultQuery varchar(8000) = ''
select @resultQuery += @var + ' ' + COLUMN_NAME + '; '
FROM information_schema.columns where table_name = 'myTable'
print @resultQuery
exec (@resultQuery)
您正在寻找的只能使用动态查询来实现。
答案 3 :(得分:0)
你有两个选择,一开始就想到我: