如何在没有聚合的情况下进行旋转?
Posted
技术标签:
【中文标题】如何在没有聚合的情况下进行旋转?【英文标题】:How to pivot without an aggregate? 【发布时间】:2018-12-17 02:52:14 【问题描述】:我有一些示例数据,如下所示,希望有人可以帮助我。
Date WellName Reading
----------------------------------------
11/30/2018 12:00:00 AM Well One 10
11/30/2018 12:00:00 AM Well Two 20
11/30/2018 12:00:00 AM Well Three 10
12/1/2018 12:00:00 AM Well One 14
12/1/2018 12:00:00 AM Well Two 25
12/1/2018 12:00:00 AM Well Three 11
12/2/2018 12:00:00 AM Well One 17
12/2/2018 12:00:00 AM Well Two 43
12/2/2018 12:00:00 AM Well Three 27
12/3/2018 12:00:00 AM Well One 25
12/3/2018 12:00:00 AM Well Two 56
12/3/2018 12:00:00 AM Well Three 67
12/16/2018 12:00:00 AM Well One 10
12/16/2018 12:00:00 AM Well Three 10
12/16/2018 12:00:00 AM Well Two 11
我需要的是顶部列出的日期,并认为 PIVOT 可以解决问题,但我似乎无法让它发挥作用。我不需要求和值或任何东西,我只需要翻转数据。
当没有日期时我还需要一个值,所以我假设我需要创建一个日期表并加入它。
有什么想法或建议吗?
【问题讨论】:
请显示您想要达到的结果。 这是我想要实现的目标(没有为所有日期添加列,但希望你明白)..11/30/2018,12/1/2018,12 /2/2018,12/3/2018,12/4/2018...12/16/2018 一号井,10,14,17,25,0,...10 二号井,20,25,43, 56,0,...10 井三,10,11,27,67,0,...11 “我不需要对值求和或任何东西,我只需要翻转数据。”您仍然会使用聚合到 PIVOT,因为您将希望按日期分组并且(可能)没有其他内容。 “当没有日期时,我还需要有一个值,所以我假设我需要创建一个日期表并加入它。”这是明智的做法,是的。另一种选择是即时执行,但我认为这总体上更麻烦。 当您想使用聚合函数(但实际上并不需要它)时,sql 查询中的典型事情是只使用 min/max 就可以了。当然,要确保您的数据全部正确,否则最小值/最大值可能会给出不一致的结果。 这是一个示例,因为您在列中使用日期,所以您需要构建动态查询:***.com/questions/27422109/… 【参考方案1】:日期可以翻转,但是你要根据日期填写什么值,无论是好名还是阅读。
这里我使用了wellname。你可以试试下面的代码。
create table stk_test2(dt datetime,wellname varchar(15),reading int)
select * from stk_test2
declare @col nvarchar(max)
select @col =
(select replace(replace(STUFF((SELECT distinct ',[' +
convert(varchar(20),dt,21) as dt
FROM stk_test2
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, ''),'.',''),',','],'))+']'
select @col
declare @sql nvarchar(max)
select
@sql = 'select * from
(
select dt,wellname from stk_test2
)ds
pivot(
Min(wellname)
for dt in ('+@col+')
)fropp'
EXEC Sp_executesql @sql
【讨论】:
【参考方案2】:感谢大家的建议 - 都非常有用。我最终使用了以下查询并将结果放入我正在使用的软件中的交叉表组件中......
declare @DateTable table (date DATETIME, PRIMARY KEY (date))
DECLARE
@basedate DATETIME,
@offset INT
SELECT
@basedate = 'varFrom',
@offset = 1
INSERT INTO @DateTable SELECT @basedate
WHILE ( DATEADD(DAY, @offset, @basedate) <= 'varTo')
BEGIN
INSERT INTO @DateTable SELECT DATEADD(DAY, @offset, date) FROM @DateTable where DATEADD(DAY, @offset, date) <= 'varTo'
SELECT @offset = @offset + @offset
END
BEGIN
WITH cte AS
(
select wod.[Well One] as Reading,'Well One' as Well, Convert(date,wo.BeginDate) as BeginDate from [reports].[WorkOrders] wo
INNER JOIN reports.WorkOrderForm_WellReadingForm wod on wod.ID = wo.ID
UNION ALL
select wod.[Well Two] as Reading,'Well Two' as Well, Convert(date,wo.BeginDate) as BeginDate from [reports].[WorkOrders] wo
INNER JOIN reports.WorkOrderForm_WellReadingForm wod on wod.ID = wo.ID
UNION ALL
select wod.[Well Three] as Reading,'Well Three' as Well, Convert(date,wo.BeginDate) as BeginDate from [reports].[WorkOrders] wo
INNER JOIN reports.WorkOrderForm_WellReadingForm wod on wod.ID = wo.ID
),
CTE_Main (Well,BeginDate,ReadingChange) AS
(
SELECT rc.Well, rc.BeginDate, COALESCE(CAST(rc.Reading AS VARCHAR(20)) + ' (' + CASE WHEN rc.Reading < rp.Reading THEN '-' ELSE '+' END + CAST(rc.Reading - rp.Reading AS VARCHAR(20)) + ')',CAST(rc.Reading as VARCHAR(20))) as ReadingChange
FROM cte rc --reading current
LEFT JOIN cte rp --reading prior
ON rc.Well = rp.Well
AND rc.BeginDate = DATEADD(DAY,1,rp.BeginDate)
)
select well.Well,well.ReadingChange, CONVERT(date,cal.date) as date from @DateTable cal
LEFT JOIN CTE_Main well on well.BeginDate = cal.date
ORDER BY cal.date
END
【讨论】:
以上是关于如何在没有聚合的情况下进行旋转?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有操作的情况下对 Pandas 数据框进行分组或聚合