存储过程&联盟

时间:2013-01-16 18:07:09

标签: sql-server stored-procedures union

我正在创建一个非常简单的数据验证存储过程。我有几个我希望运行的sql语句,只是显示结果以与源进行比较。我将sql语句与union结合在一起,但是你不能将不同数据类型的列合并在一起。希望有人会建议更好的方法继续进行?

USE [employee_data]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[data_employee]

AS
BEGIN

declare @LtYear as varchar(10)
set @LtYear = '2012'

SELECT 'Sum of total salary for ' + @LtYear as title, sum([Total_Salary]) as Salary
From [employee_data].[dbo].[employee]
where year = @LtYear

UNION
select 'Overall Average Salary ' + @LatestYear as title, avg([Total_Salary]) as     'Average Salary'
From [employee_data].[dbo].[employee]
where year = @LtYear

SELECT 'Employee Name - 1' as title, first_name+' '+last_name 
From [employee_data].[dbo].[employee]
where year = 2012 --@LtYear
and [First_Name] = 'first'
and [Last_Name] = 'last'

UNION
SELECT 'Individual Employee Experience ' + @LtYear as title, cast([work_Exp]as varchar) as 'Work Experience'
From [employee_data].[dbo].[employee]
where year = @LtYear
and [First_Name] = 'first'
and [Last_Name] = 'last'

我希望看到如下结果:

总薪资总额:50000000
总体平均工资:37000
员工姓名 - 1:最后一名 2012年个人员工经历:12

1 个答案:

答案 0 :(得分:1)

为什么不将它翻转到侧面以便你不必使用联合,你只需要横向扫描数据:

SELECT [Year] = @LtYear,
  [Sum of Total Salary] = s.s, 
  [Average Salary] = s.a,
  [Employee Name] = e.first_name + ' ' + e.last_name,
  [Work Experience] = CONVERT(VARCHAR(12), e.work_Exp
FROM employee_data.dbo.employee AS e
CROSS JOIN
(
  SELECT SUM(Total_Salary), AVG(Total_Salary)
  FROM employee_data.dbo.employee
  WHERE [Year] = @LtYear
) AS s(s,a)
WHERE e.[Year] = @LtYear
AND e.First_Name = @first_name
AND e.Last_Name = @last_name;

不确定您是否真的想要对'first''last'进行硬编码,但我怀疑这些参数会更好,特别是如果您要多次引用它们。

鉴于您的要求是由Excel驱动的,可以尝试:

DECLARE @y CHAR(4);
SET @y = CONVERT(CHAR(4), @LtYear);

SELECT col1 = 'Sum of total salary for ' + @y, 
  col2 = CONVERT(NVARCHAR(255), sum(Total_Salary) as Salary)
  From employee_data.dbo.employee
  where [year] = @LtYear
UNION ALL
SELECT 'Overall Average Salary ' + @y, 
  CONVERT(NVARCHAR(255), avg(Total_Salary))
  From employee_data.dbo.employee
  where [year] = @LtYear
UNION ALL
SELECT 'Employee Name - 1', 
  CONVERT(NVARCHAR(255), first_name+' '+last_name)
  From employee_data.dbo.employee
  where [year] = @LtYear
  and First_Name = 'first'
  and Last_Name = 'last'
UNION ALL
SELECT 'Individual Employee Experience ' + @y, 
  CONVERT(NVARCHAR(255), work_Exp)
  From employee_data.dbo.employee
  where [year] = @LtYear
  and First_Name = 'first'
  and Last_Name = 'last';

请注意一些变化:

  • 删除了所有别名 - 无论如何,它们在联盟中的第一个语句后被忽略。
  • 使用针对第二列的显式转换为希望兼容的数据类型。
  • 将所有关键字(例如year)正确括在方括号中。删除了那些不必要的东西 - 它们只会使查询更难阅读。
  • 创建了year参数的字符串版本,以便可以将其附加到第一列,而无需执行任何转换。

现在,你已经愚弄了这个问题,还有更多我们看不到的查询。但我仍然认为更好的方法是将工会放在基表上并以这种方式执行(特别是如果你对同一个表有10或15个查询)。这不一定会以不同的方式执行,但它将更容易维护 lot

;WITH x AS 
(
  SELECT 
    y = CONVERT(CHAR(4), @LtYear),
    [ss] = CONVERT(NVARCHAR(255), s.s), 
    [as] = CONVERT(NVARCHAR(255), s.a),
    [en] = CONVERT(NVARCHAR(255), e.first_name + ' ' + e.last_name),
    [we] = CONVERT(NVARCHAR(255), e.work_Exp)
  FROM employee_data.dbo.employee AS e
  CROSS JOIN
  (
    SELECT SUM(Total_Salary), AVG(Total_Salary)
    FROM employee_data.dbo.employee
    WHERE [Year] = @LtYear
  ) AS s(s,a)
  WHERE e.[Year] = @LtYear
  AND e.First_Name = @first_name
  AND e.Last_Name = @last_name
)
SELECT 'Sum of total salary for ' + y, [ss] FROM x
UNION ALL
SELECT 'Overall average salary for ' + y, [as] FROM x
UNION ALL
SELECT 'Employee Name - 1', [en] FROM x
UNION ALL
SELECT 'Individual Employee Experience ' + y, [we] FROM x;

除此之外,我认为你的方法首先是非常麻烦的。您是通过将这些查询拼凑在一起并手动将结果粘贴到Excel中来执行数据验证的吗?当然有一种更自动化的方法来实现这一点,而不是试图定制一个笨拙的SQL查询以符合您的过程,您应该改进过程......