在 SQL Server 中获取特定年份中的列作为月份名称

Posted

技术标签:

【中文标题】在 SQL Server 中获取特定年份中的列作为月份名称【英文标题】:Get Columns as Month Name in a specific year in SQL Server 【发布时间】:2020-11-25 16:38:27 【问题描述】:

我在 SQL Server 中有两个表:

    Employee(id、empid、empname)和 EmpSales (id, empid, billdtae, sale)

EmpSales 表有多年的员工销售数据。

我的查询是,我希望 Empid 作为第一列,EmpName 作为第二列,所有月份的名称作为特定年份的一月、二月、三月等后续列,以及与员工和月份作为数据。

我已经尝试并搜索了很多,但无法找到正确的解决方案。我可以通过以下查询获得EmpidEmpName,但其余的解决方案正是我要寻找的。​​p>

SELECT S.empid, E.empname
FROM empsale S
INNER JOIN employee E ON S.empid = E.empid 
WHERE YEAR(S.bill_date) = YEAR(GETDATE()) 
GROUP BY S.empid, E.empname 
ORDER BY CONVERT(INT,S.empid)

这个查询只返回empidempname 但是想要的是这样的

如果有人可以用正确的查询/答案回复我或提供任何更好的解决方案,那将是一个很大的帮助。

【问题讨论】:

样本数据和预期结果将帮助我们帮助您,但是,这称为“数据透视”、交叉表或条件聚合。 好吧,我也想知道同样的答案,但说真的,我从未在 SQL 中使用过数据透视。我非常了解 Excel 中的枢轴。 有什么方法可以向我提供相同的查询。并告诉我如何提供样本数据。 如果没有样本数据和预期结果,我无法向您展示如何回答问题,不。见Tips for asking a good Structured Query Language (SQL) question 第一步是计算您感兴趣的一年内每个月所需的值。完成该工作后,您可以将行转为列 - 您可以通过搜索找到这些示例。 【参考方案1】:

我已经通过以下查询获得了结果。

SELECT
  *
FROM
  (
    SELECT
      S.empid as Empid,
      E.empname as Employee,
      SUM(S.saleamt) as SaleAmt,
      DATENAME(MM, s.bill_date) as slmnth
    FROM
      empsale S
      INNER JOIN employee E ON S.empid = E.empid
    WHERE
      YEAR(S.bill_date) = YEAR(GETDATE())
    GROUP BY
      S.empid,
      E.empname,
      DATENAME(MM, s.bill_date)
  ) as bd PIVOT (
    SUM(SaleAmt) FOR slmnth in (
      [January],
      [February],
      [March],
      [May],
      [June],
      [July],
      [August],
      [September],
      [October],
      [November]
    )
  ) AS pvtbl

【讨论】:

【参考方案2】:

这是一种无需求助于 PIVOT 和动态 SQL 的简单方法:

DECLARE @Employee table ( empid int, empname varchar(50), id int IDENTITY(1,1) );
INSERT INTO @Employee VALUES
    ( 1000, 'Bill Gates' ), ( 1001, 'Elon Musk' );

DECLARE @EmpSales table ( empid int, bill_date date, sale int );
INSERT INTO @EmpSales VALUES
    ( 1000, '01/01/2020', 100 ), ( 1000, '01/15/2020', 100 ), ( 1000, '02/15/2020', 50 ), ( 1000, '04/01/2020', 25 );

SELECT
    e.empid, e.empname, s.*
FROM @Employee e
OUTER APPLY (

    SELECT
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'January' THEN n.sale ELSE 0 END ), 0 ) AS [Jan],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'February' THEN n.sale ELSE 0 END ), 0 ) AS [Feb],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'March' THEN n.sale ELSE 0 END ), 0 ) AS [Mar],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'April' THEN n.sale ELSE 0 END ), 0 ) AS [Apr],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'May' THEN n.sale ELSE 0 END ), 0 ) AS [May],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'June' THEN n.sale ELSE 0 END ), 0 ) AS [Jun],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'July' THEN n.sale ELSE 0 END ), 0 ) AS [Jul],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'August' THEN n.sale ELSE 0 END ), 0 ) AS [Aug],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'September' THEN n.sale ELSE 0 END ), 0 ) AS [Sep],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'October' THEN n.sale ELSE 0 END ), 0 ) AS [Oct],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'November' THEN n.sale ELSE 0 END ), 0 ) AS [Nov],
        ISNULL( SUM( CASE WHEN DATENAME( month, n.bill_date ) = 'December' THEN n.sale ELSE 0 END ), 0 ) AS [Dec]
    FROM @EmpSales AS n
    WHERE
        n.empid = e.empid
        AND YEAR( n.bill_date ) = YEAR( GETDATE() )

) AS s
ORDER BY
    e.empid;

返回

+-------+------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| empid |  empname   | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec |
+-------+------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  1000 | Bill Gates | 200 |  50 |   0 |  25 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |
|  1001 | Elon Musk  |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |
+-------+------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

【讨论】:

哇,你真好。你太棒了。这实际上是我想要的结果,我不知道该用什么词来感谢你。但是,根据上一个答案中的线索,我在 SQL 中搜索了 Pivot,并且在观看了来自 'wise owl' SQL 编程的视频教程后,我设法获得了相同的结果。我会放代码。 先生,我想知道如何在此查询中应用一个细微的变化。假设员工表中有 100 名员工,但 emsales 表中只有 30 名员工。根据上面的查询,它显示所有员工。我希望它只显示 empales 表中的员工应该在结果中。我的意思是说那些没有做过任何销售的员工不应该出现在最终结果中。 将外部应用更改为交叉应用。

以上是关于在 SQL Server 中获取特定年份中的列作为月份名称的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2008 中从月份和年份创建日期

SQL Server 2005获取任何年份中任何月份的第一个和最后一个日期

sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期

将表列值存储到变量中(SQL Server)

SQL Server Reporting Services 2008 中的列和行分组

SQL Server 2012 中的年份计算