Sql:将行转变成列

2024-01-03

考虑下面的例子,我有一个Person包含人员记录和人物属性包含链接到人员的可选属性的表:

表:人



ID    Name
1     Joe Bloggs
2     Jane Doe
  

表人员属性



PersonId  Key         Value
1         Age         27            
2         HairColor   Brown
  

我将如何编写一个查询来返回具有属性的所有人员,就好像他们是列一样?我需要的结果集是:



ID    Name        Age    HairColor
1     Joe Bloggs  27     
2     Jane Doe           Brown
  

因此,本质上我需要编写一个查询,获取所有具有唯一属性键的所有人员记录,并将其转置为具有每个人员记录的值的列。

请注意,主键人物属性表是PersonID and Key合并起来,这样我们就不会有特定键和人员的重复条目。

显然我可以添加Age and 发色作为字段Person表并且不使用人物属性表根本没有,但这只是一个说明问题的例子。实际上,我有大量的自定义属性,这些属性对于不同的人员记录差异很大,因此这样做是不切实际的。


我不能谈论 MySQL,但在 PostgreSQL 中你可以使用 crosstab 函数表函数 http://www.postgresql.org/docs/current/static/tablefunc.html module:

CREATE OR REPLACE VIEW PersonAttributePivot AS
    SELECT PersonId AS ID, Age, HairColor
    FROM crosstab
    (
       'SELECT PersonId, Key, Value FROM PersonAttribute',
       'SELECT DISTINCT Key FROM PersonAttribute ORDER BY Key'
    )
    AS
    (
        PersonId integer,
        Age text,
        HairColor text
    );

加入查询:

SELECT id, name, age, haircolor
FROM Person JOIN PersonAttributePivot USING(id)
ORDER BY id;

想要的结果:

 id |    name    | age | haircolor 
----+------------+-----+-----------
  1 | Joe Bloggs | 27  | 
  2 | Jane Doe   |     | Brown
(2 rows)

正如你所看到的,我将明确的列列表放入PersonAttributePivot看法。我不知道任何带有隐式列列表的“自动透视”创建方式。

EDIT:

For huge列列表(假设总是texttype)作为一种解决方法,我看到了这样一点点修改的方法:

动态类型创建(这里简单地基于 Java):

Class.forName("org.postgresql.Driver");
Connection c =
        DriverManager.getConnection("jdbc:postgresql://localhost/postgres", "postgres", "12345");
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT DISTINCT Key FROM PersonAttribute ORDER BY Key");
List<String> columns = new ArrayList<String>();

while (rs.next())
    columns.add(rs.getString(1));

System.out.println("CREATE TYPE PersonAttributePivotType AS (");
System.out.println("\tPersonId integer,");
for (int i = 0; i < columns.size(); ++i)
{
    System.out.print("\t" + columns.get(i) + " text");
    if (i != columns.size() - 1)
        System.out.print(",");
    System.out.println();
}
System.out.println(");");

Result:

CREATE TYPE PersonAttributePivotType AS (
    PersonId integer,
    Age text,
    HairColor text
);

函数包装器:

CREATE OR REPLACE FUNCTION crosstabPersonAttribute(text, text)
    RETURNS setof PersonAttributePivotType
    AS '$libdir/tablefunc','crosstab_hash' LANGUAGE C STABLE STRICT;

自动视图创建:

CREATE OR REPLACE VIEW PersonAttributePivot AS
    SELECT * FROM crosstabPersonAttribute
    (
       'SELECT PersonId, Key, Value FROM PersonAttribute',
       'SELECT DISTINCT Key FROM PersonAttribute ORDER BY Key'
    );

Result:

TABLE PersonAttributePivot;
 personid | age | haircolor
----------+-----+-----------
        1 | 27  |
        2 |     | Brown
(2 rows)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Sql:将行转变成列 的相关文章

随机推荐

  • 如何用Python编写下载进度指示器?

    我正在编写一个小应用程序来通过 http 下载文件 例如 所描述的here https stackoverflow com questions 22676 how do i download a file over http using p
  • Cucumber-jvm @after 与 Appium 驱动程序

    我在用着cucumber jvm 并努力在全球范围内实施 After应该执行的方法只有一次所有场景执行完成后 这 After方法应该退出appium驱动程序 现在 After钩子在之后执行each运行场景 这意味着每次都应该从头开始创建驱动
  • jQuery 上的 trigger('click') 和 click() 有什么区别

    我正在寻找这两者之间的性能差异 我在 SSE 中找不到关于这个主题的好的答案 一些例子会有很大帮助 如果你查看 jQuery 代码 你会发现所有click does 是执行trigger click jQuery each blur foc
  • 使用 scala 和 GAE 玩框架

    有谁知道如何让 Play 框架的 scala 版本在 Google App Engine 中运行 此时我只是尝试让默认应用程序运行 我正在使用带有 gae 1 4 和 scala 0 9 1 模块的 Play 1 2 2 我创建了一个默认应
  • 如何在特征值中转置张量

    我试图获得两个张量的矩阵乘积 其中一个张量应该在相乘之前转置 At B 到目前为止我发现的是没有任何转置和两个矩阵转置的矩阵乘积 我正在寻找一种方法 可以直接收缩两个张量并转置其中一个张量 或者在收缩一个张量之前转置一个张量 我发现 转置效
  • 使用 C# 通过数据库中存储的文件路径在 Crystal Reports 10 中显示图像

    我有一个 C Windows 应用程序 它将员工数据存储到 MYSQL 数据库中 包括他们的图片文件路径 192 168 13 6 IDPictures Unknown jpg 有人可以帮助我如何通过从数据库读取文件路径来显示 Crysta
  • php preg_replace 匹配字符串但仅替换其中的一部分

    我有这样的文字 Retailer ul Amazon foloseste metode severe pentru a si descuraja etc angajatii din depozite sa nu mai fure din p
  • 使用 SELECT 结果作为其他 SELECT 中的 COLUMN 名称

    是否可以使用选择的结果作为字符串与其他选择中列名中的另一个字符串连接 Example SELECT brand FROM articles a WHERE a id 12345678 结果 BRAND A 我现在想要连接 PRICE to
  • 如何使用 LoadImage 和 StretchDIBits 绘制 PNG 图像?

    这与问题有关如何使用 Win32 GDI 加载 PNG 图像 如果可能 不要使用 GDI https stackoverflow com questions 4567875 how would i load a png image usin
  • 从 PyQt GUI 类外部访问 GUI 元素 text( )

    Ui MainWindow 是由设计器和 pyuic 生成的 py 文件 我想将 PyQt GUI 元素文本值传递到另一个文件并执行一些基本操作并返回结果 父文件 from PyQt4 import QtCore QtGui try fro
  • 将 SQL 查询替换为 LINQ 查询

    我有SQL检查今天的查询 根据表中存储 3 个字母字符的字段进行检查 如下所示 如果今天是星期二我需要归还记录 我有这样的 SQL 查询 SELECT TOP 1 EndTime StartTime OrderDay FROM dbo Se
  • .NET 4.6 之前的 Buffer.MemoryCopy 的替代方案

    我正在尝试将一些 NET 4 6 代码降级到 NET 4 5 这是我目前正在使用的代码块 fixed byte destination dataBytes Buffer MemoryCopy data destination dataLen
  • 为什么 JavaMail Transport.send() 是静态方法?

    我正在修改我没有编写的使用 JavaMail 的代码 并且在理解为什么 JavaMail API 是这样设计的方面遇到了一些困难 我有一种感觉 如果我理解的话 我可以做得更好 We call transport session getTra
  • Java使用String.format进行十进制格式化?

    我需要将十进制值格式化为字符串 其中我始终显示至少 2 位小数 最多 4 位小数 例如 34 49596 would be 34 4959 49 3 would be 49 30 可以使用 String format 命令来完成此操作吗 或
  • 如何在 yocto 中打补丁?

    我正在尝试使用 yocto poky warrior 和 meta tegra Warriors l4t r32 2 层为 jetson nano 构建图像 我一直在关注这个线程 https stackoverflow com questi
  • T4 vs CodeDom vs Oslo [已关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 连接集合返回函数 (SRF) 并访问 SQLAlchemy 中的列

    假设我有一个activity表和一个subscription桌子 每个活动都有一个对其他对象的通用引用的数组 每个订阅都有一个对同一集中的其他对象的通用引用 CREATE TABLE activity id serial primary k
  • 检查特定的exe文件是否正在运行

    我想知道如何检查特定位置的程序是否正在运行 例如 test exe 有两个位置 c loc1 test exe 和 c loc2 test exe 我只想知道 c loc1 test exe 是否正在运行 而不是 test exe 的所有实
  • 如何动态改变datagrid行的背景颜色?

    似乎有各种黑客可以改变数据网格行的背景颜色 但所有这些似乎都发生在渲染时 See 在 Adob e Flex 中设置数据网格行的背景颜色 https stackoverflow com questions 748213 setting ba
  • Sql:将行转变成列

    考虑下面的例子 我有一个Person包含人员记录和人物属性包含链接到人员的可选属性的表 表 人 ID Name 1 Joe Bloggs 2 Jane Doe 表人员属性 PersonId Key Value 1 Age 27 2 Hair