将该UNPIVOT
函数应用于未规范化的数据时,SQL Server 要求数据类型和长度相同。我明白为什么数据类型必须相同,但为什么 UNPIVOT 要求长度相同?
假设我有以下需要逆透视的示例数据:
CREATE TABLE People
(
PersonId int,
Firstname varchar(50),
Lastname varchar(25)
)
INSERT INTO People VALUES (1, 'Jim', 'Smith');
INSERT INTO People VALUES (2, 'Jane', 'Jones');
INSERT INTO People VALUES (3, 'Bob', 'Unicorn');
Run Code Online (Sandbox Code Playgroud)
如果我尝试 UNPIVOTFirstname
和Lastname
列类似于:
select PersonId, ColumnName, Value
from People
unpivot
(
Value
FOR ColumnName in (FirstName, LastName)
) unpiv;
Run Code Online (Sandbox Code Playgroud)
SQL Server 生成错误:
Msg 8167, Level 16, State 1, Line 6
“姓氏”列的类型与 UNPIVOT 列表中指定的其他列的类型冲突。
为了解决错误,我们必须使用子查询首先将Lastname
列强制转换为与以下相同的长度Firstname …
我有以下形式的查询:
SELECT ...
FROM ColumnstoreTable cs
CROSS APPLY (
SELECT *
FROM (VALUES
('A', cs.DataA)
, ('B', cs.DataB)
, ('C', cs.DataC)
) x(Col0, Col1)
) someValues
Run Code Online (Sandbox Code Playgroud)
这从 Columnstore 支持的子查询 ( ColumnstoreTable
) 中获取每一行并将这些行相乘。这本质上是一个UNPIVOT
. 真正的查询比这更大。这部分查询会进入其他处理。
这里的问题是这CROSS APPLY
是作为一个循环连接实现的,这是一个合理的选择。不幸的是,循环连接不支持批处理模式。
这部分查询对性能非常关键,我怀疑以批处理模式运行它可能对性能非常有益。
我怎样才能重写这个查询,这样我就不会退出批处理模式?
我确实尝试使用临时表而不是VALUES
,但这并没有改变这样一个事实,即没有相等连接条件来进行哈希连接。
我有一个有点复杂的 Oracle 查询,需要大约半小时才能完成。如果我采用查询的慢部分并单独运行它,它会在几秒钟内完成。这是隔离查询的 SQL Monitor 报告的屏幕截图:
以下是作为完整查询的一部分运行时的相同逻辑:
颜色对应于两个屏幕截图中的相同表格。对于慢查询,OracleMERGE JOIN
在JOIN
. 结果,大约有 1.5 亿个中间行被不必要地处理。
我可以通过查询提示或重写来解决这个问题,但我想尽可能多地了解根本原因,以便将来避免这个问题,并可能向 Oracle 提交错误报告。每次我得到糟糕的计划UNPIVOT
时,查询文本中的内容都会转换为UNION ALL
计划中的一个。为了进一步调查,我想防止该查询转换发生。我一直找不到这个转换的名字。我也找不到可以阻止它的查询提示或下划线参数。我正在开发服务器上进行测试,所以一切顺利。
有什么我可以做,以防止的查询转换UNPIVOT
到UNION ALL
?我在 Oracle 12.1.0.2 上。
由于 IP 原因,我无法共享查询、表名或数据。我无法想出一个简单的复制品。话虽如此,我不清楚为什么需要这些信息来回答这个问题。下面是 UNPIVOT 查询的示例以及作为 UNION ALL 实现的相同查询。
我有一个包含以下数据的表格
First Second Third Fourth Fifth Sixth
2013-08-20 2013-08-21 2013-08-22 2013-08-23 2013-08-24 2013-08-25
Run Code Online (Sandbox Code Playgroud)
并使用 UNPIVOT
SELECT Data
,DATENAME(DW, Data) AS DayName
FROM Cal
UNPIVOT(Data FOR D IN (
First,
Second,
Third,
Fourth,
Fifth,
Sixth )) AS unpvt
Run Code Online (Sandbox Code Playgroud)
我得到以下结果
Data DayName
2013-08-20 Tuesday
2013-08-21 Wednesday
2013-08-22 Thursday
2013-08-23 Friday
2013-08-24 Saturday
2013-08-25 Sunday
Run Code Online (Sandbox Code Playgroud)
现在我的问题是我们可以动态地将列名传递给 the ,UNPIVOT
以便当表中的列增加时我们可能不必更改语句。
In this code I am converting the subjects(columns) English , Hindi , Sanskrith , into rows
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsUnpivot
=stuff(
(select ',' + quotename (C.name)
from sys.columns c
where c.object_id = OBJECT_ID('dbo.result2')
for xml path(''), TYPE) .value('.', 'NVARCHAR(MAX)'),
1, 8, ''
);
print @colsunpivot
select @query
= 'select Name, Subject,Marks
from result2
unpivot
(
marks for subject in (' + @colsunpivot + ')) as tab'
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
Please explain what does for xml …
我正在尝试在兼容级别为 80 的 SQL Server 2008 SP3 数据库上使用 UNPIVOT 提取数据。这应该意味着 UNPIVOT 不起作用,但在我的情况下它在某些情况下起作用......
作品:
表单的独立 SELECT 查询:
SELECT...FROM...UNPIVOT...WHERE...GROUP BY
Run Code Online (Sandbox Code Playgroud)
不起作用:
同一查询,在LEFT JOIN ()
同一服务器内不同数据库上的其他表上。全部在兼容性级别 80。
我收到通常的错误消息:
Msg 325, Level 15, State 1, Line 165
Incorrect syntax near 'UNPIVOT'. You may need to set the compatibility level
of the current database to a higher value to enable this feature. See help for
the SET COMPATIBILITY_LEVEL option of ALTER DATABASE.
Run Code Online (Sandbox Code Playgroud)
UNPIVOT
解决方法似乎很麻烦,如果可能的话,我希望这个查询是独立的和可刷新的。如果我可以让查询独立工作,那么应该可以在JOIN
.
问题:
为什么有时会这样?
在这些条件下如何实现UNPIVOT
子查询JOIN
?
Unpivot …
我需要取消旋转下表,以便输出如下图所示。
这是否需要我对数据集执行两次 UNPIVOT,或者我可以通过使用一次 UNPIVOT 并指定所有可用的 Month 和 Value 列来完成我的预期输出吗?
我的脚本应该类似于以下内容来完成我需要的吗?
Select ID, Name, Age, Gender,Month,Value
FROM
(Select ID, Name, Age, Gender,Month1,Month2,Month3,Month4,Value1,Value2,Value3,Value4
FROM MyTable
) as cp
UNPIVOT
(
Month FOR Months IN (Month1, Month2, Month3,Month4),
Value for Values IN (Value1,Value2,Value3,Value4)
) AS up;
Run Code Online (Sandbox Code Playgroud) 考虑下表:
id title genre1 genre2 genre3 genre4 genre5
1 Movie1 Thriller Crime NULL NULL NULL
2 Movie2 Fantasy NULL NULL NULL NULL
3 Movie3 Political Philosophical Historical NULL NULL
4 Movie4 Science Fiction NULL NULL NULL NULL
Run Code Online (Sandbox Code Playgroud)
当我取消旋转流派 1、流派 2 时,删除了 NULL 值,例如,Movie1 的行将是:
id title genre original_column
1 Movie1 Thriller genre1
1 Movie1 Crime genre2
Run Code Online (Sandbox Code Playgroud)
有没有办法包含 NULL 值,例如:
id title genre original_column
1 Movie1 Thriller genre1
1 Movie1 Crime genre2
1 Movie1 NULL genre3
1 Movie1 NULL genre4
1 …
Run Code Online (Sandbox Code Playgroud) 我管理一个应用程序,该应用程序有多个用户通过 Web 前端将数据输入到 MSSQL 数据库中。每个单独的“记录”在多个表中可以有大约 100 个数据库列(有时在同一个表中有多个行)。编写 SQL 查询将在每个“记录”中输出 1 行,其中包含我们用于报告目的所需的所有列,这是相对简单的,例如:
Assessor Date Length Colour Weight
Steve 2/4/17 23.4 NULL 45
John 4/4/17 NULL Blue NULL
Brenda 4/4/17 NULL NULL NULL
Run Code Online (Sandbox Code Playgroud)
我想生成一个简单的输出,列出未记录数据的所有内容,即保持 NULL 的字段。例如:
Assessor Date Field
Steve 2/4/17 Colour
John 4/4/17 Length
John 4/4/17 Weight
Brenda 4/4/17 Length
Brenda 4/4/17 Length
Brenda 4/4/17 Colour
Brenda 4/4/17 Weight
Run Code Online (Sandbox Code Playgroud)
目前我已经尝试了以下方面的内容:
select
assessor
,date
,Field = 'Length'
from
dbo.table1
where [Length] is NULL
UNION ALL
select
assessor
,date
,Field = 'Colour'
from …
Run Code Online (Sandbox Code Playgroud) 我有一张大致像这样的桌子。
(Pk int, Year int, Week1, Week2, .., Week53)
每个“周”列中的值是销售数据。我想要做的是从第一个表格中创建一个新表格 -
(PK int, WeekYear, SalesData)
其中“WeekYear”是年份和周数的串联,SalesData 是前一个表中相应字段的相同 salesdata。(只是想暂时取消选择)
SELECT pk,
[1],
[2],
...
[1000]
FROM (SELECT * FROM SalesTable) st
PIVOT
(
AGGREGATE(pk) -- no idea what to use here
FOR pk IN [1],
[2],
...
[1000]
);
Run Code Online (Sandbox Code Playgroud)
我目前的尝试毫无意义,因为我不确定要在我的数据集上应用哪个聚合函数。我在辨别创建新专栏 YearWeek 的最佳方式时也遇到了一些麻烦。
这似乎是PIVOT 的一个明显用途(我需要转置表格)。但是,我在思考如何正确完成它时遇到了很多麻烦。这样做的最佳方法是什么?
假设我在 SQL Server 2008 中有一个这样的表:
id | name | qty
-------------------
1 | john | 1
2 | bill | 3
3 | mary | 2
4 | jill | 5
Run Code Online (Sandbox Code Playgroud)
我想查询此表并为每批返回 1 行,最多为 2。因此,查询结果如下所示:
id | name | qty
-------------------
1 | john | 1
2 | bill | 2
2 | bill | 1
3 | mary | 2
4 | jill | 2
4 | jill | 2
4 | jill | 1
Run Code Online (Sandbox Code Playgroud)
这可以在不使用光标的情况下整齐地完成吗?这可以使用 unpivot 吗?
顺便说一下,该 …
典型的数据库表可能如下所示:
date-------geography---clicks---cost---conversions
___________________________________________________
1/1/2010---Kansas------56-------12-----1
Run Code Online (Sandbox Code Playgroud)
转换后,它看起来像这样。
date-----geography---metric_name---metric_value
____________________________________________
1/1/2010-Kansas------clicks--------56
1/1/2010-Kansas------cost----------12
1/1/2010-Kansas------conversions---1
Run Code Online (Sandbox Code Playgroud)
转置表更适用于收集的指标数量频繁变化的某些用例。
在转置表中是否有类似结构的表的标准名称?
我有诸如role1
、role2
、role3
等列。它们都是布尔值。
我想在此表上创建一个视图,该视图具有类型为 的角色列text[]
。如果有列TRUE, FALSE, TRUE
,则视图将包含["role1", "role3"]
.
有什么好的方法可以做到这一点,并且不会爆炸成大量的CASE WHEN
\xc2\xb4s 吗?澄清一下,我可以使用 O(n) CASE WHEN
,但不能使用 O(2^n) ,这是目前似乎需要的。:)
unpivot ×13
sql-server ×8
t-sql ×3
array ×1
batch-mode ×1
columnstore ×1
cross-apply ×1
cursors ×1
oracle ×1
oracle-12c ×1
pivot ×1
postgresql ×1
terminology ×1
union ×1
view ×1