繁体   English   中英

将表格格式更改为透视

[英]Change table format to pivot

在这个问题的延续中

主要代码:

CREATE TABLE params
(
    id_param smallint PRIMARY KEY,
    name varchar(50) NOT NULL
)

CREATE TABLE objects_params
(
    id_object int,
    id_param smallint NOT NULL,
    cdate smalldatetime,
    value int
)

INSERT INTO dbo.params (id_param, name)
VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), 
       (5, 'e'), (6, 'f'), (7, 'g')

INSERT INTO dbo.objects_params (id_object, id_param, cdate, value)
VALUES (1, 1, '20191206',NULL), (1, 2,'20191212', 100), (1, 1, '20191201', 110),
       (2, 4, '20191211',120), (2, 1,'20190101', 130), (2, 3, '20191212', 140),
       (2, 4, '20191111',150), (2, 3,'20190201', 160), (2, 3, '20190312', 170),
       (2, 3, '20191201', 175),(2, 3, '20191202', 180), (2, 3, '20191203', 185),
       (2, 3, '20191204', 190)

然后我需要获取最接近给定日期的值列表:

DECLARE @userdate DATETIME
SET @userdate='20191202'

DECLARE @names as VARCHAR(MAX)
SELECT @names =
COALESCE(@names + ', ','') + QUOTENAME(name)
FROM
   (SELECT distinct name
    FROM objects_params 
    JOIN params ON objects_params.id_param = params.id_param
   ) AS B;

With t_sql as ( 
    SELECT  id_object, objects_params.id_param, name, cdate, value  
    FROM objects_params 
    JOIN params ON objects_params.id_param = params.id_param)
    --Where value <> ''

SELECT id_object, id_param, name, cdate, value  
FROM 
    (
        SELECT RANK() OVER (PARTITION BY id_object, id_param ORDER BY abs(datediff(ss, @userdate,cdate)) ASC) AS DateRank, *
        FROM t_sql
        WHERE cdate < @userdate
    ) 
AS DetailsRanking
WHERE DetailsRanking.DateRank=1

并得到一个这样的表:

id_object id_param   name      cdate      value
-----------------------------------------------
   1         1         a     2019-12-01    110
   2         1         a     2019-01-01    130
   2         3         c     2019-12-01    175
   2         4         d     2019-11-11    150

但是我怎样才能得到这种格式的结果:

    id_object     a         b       c      d      e      f      g   
    ---------------------------------------------------------------
       1         110      null    null   null   null   null   null
       2         130      null    175    150    null   null   null

我在这种情况下尝试使用枢轴的所有尝试都没有成功。


更新

根据@Gordon Linoff 和@xXx 的建议尝试重做使用动态 SQL 的代码,所以我们开始:

USE [DConturDb]
GO

DECLARE @userdate VARCHAR(MAX)
SET @userdate='20191202';

DECLARE @names as VARCHAR(MAX)
SELECT @names =
COALESCE(@names + ', ','') + QUOTENAME(name)
FROM
   (SELECT name
    FROM params 
   ) AS B;

DECLARE @SQL as VARCHAR(MAX)
SET @SQL = 

'WITH op as ( SELECT op.id_object, op.id_param, name, op.cdate, op.value, ROW_NUMBER() OVER (PARTITION BY op.id_object, op.id_param ORDER BY op.cdate DESC) as seqnum FROM objects_params op JOIN params p ON op.id_param = p.id_param

  WHERE op.cdate <='''+ @userdate +'''
 )

SELECT id_object, ' + @names + ' FROM ( select id_object, value, name from op where seqnum=1 ) 作为 tbl pivot ( max(value) for name in (' + @names + ') ) piv'

execute(@SQL)

完毕。

您可以使用条件聚合:

WITH op as ( 
      SELECT op.id_object, op.id_param, name, op.cdate, op.value,
             ROW_NUMBER() OVER (PARTITION BY op.id_object, op.id_param ORDER BY op.cdate DESC) as seqnum
      FROM objects_params op JOIN
           params p
           ON op.id_param = p.id_param
      WHERE op.cdate < @userdate
     )
SELECT id_object,
       MAX(CASE WHEN id_param = 1 THEN value END) as value_1,  
       MAX(CASE WHEN id_param = 2 THEN value END) as value_2, 
       . . .  
FROM op
WHERE seqnum = 1
GROUP BY id_object;

你会得到你想要的结果。

DECLARE @userdate DATETIME
   SET @userdate='20191202'
   select * from (
   select b.id_object,value,a.name from params a
   INNER JOIN objects_params b on a.id_param = b.id_param
   where cdate < @userdate--here is your parameters
   ) as t 
   pivot (sum(value) for name IN ([a],[b],[c],[d],[e],[f],[g]) ) as Pivot_tbl --pivot based on names 

SQL Fiddle - 只需将 getdate() 替换为您正在使用的变量:

MS SQL Server 2017 架构设置

CREATE TABLE Result (id_object int,id_param int,name varchar(255)
                    ,cdate date,  val int);
INSERT INTO  Result(id_object,id_param,name,cdate,val)
            VALUES (1,1,'a','2019-12-01',110)
            ,(2,1,'a','2019-01-01',130)
            ,(2,3,'c','2019-12-01',175)
            ,(2,4,'d','2019-11-11',150)

查询 1

with CTE AS (select *,
(CASE WHEN name='a' THEN val  END) AS a,
(CASE WHEN name = 'b' THEN val END) AS b,
(CASE WHEN name='c' THEN val END) AS c,
(CASE WHEN name='d' THEN val END) AS d,
(CASE WHEN name='e' THEN val END) AS e,
(CASE WHEN name='f' THEN val END) AS f,
(CASE WHEN name='g' THEN val END) AS g,             
ROW_NUMBER() OVER (PARTITION BY id_param,id_object Order By cdate) as rn
from Result
             where cdate < getdate()
group by id_object,id_param,name,cdate,val              )

select c.id_object

,max(c.a) AS a
,max(c.b) AS b
,max(c.c) AS c
,max(c.d) AS d
,max(c.e) AS e
,max(c.f) AS f
,max(c.g) AS g

from cte c
where rn=1
group by c.id_object

结果

| id_object |   a |      b |      c |      d |      e |      f |      g |
|-----------|-----|--------|--------|--------|--------|--------|--------|
|         1 | 110 | (null) | (null) | (null) | (null) | (null) | (null) |
|         2 | 130 | (null) |    175 |    150 | (null) | (null) | (null) |

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM