考虑下面的示例,其中有一个包含人员记录的 Person 表和一个包含链接到人员的可选属性的 PersonAttribute 表:
Table: Person
ID Name
1 Joe Bloggs
2 Jane Doe
Table PersonAttribute
PersonId Key Value
1 Age 27
2 HairColor Brown
我将如何编写一个查询,使所有具有属性的人都像列一样返回?我需要的结果集是:
ID Name Age HairColor
1 Joe Bloggs 27
2 Jane Doe Brown
因此,从本质上讲,我需要编写一个查询,该查询将获取所有带有所有唯一属性键的人记录,这些键被转换为具有每个人记录值的列。
请注意, PersonAttribute 表上的主键是 PersonID 和 Key的
组合,因此对于特定的key和person,我们将没有重复的条目。
显然,我可以将 Age 和 HairColor 添加为 Person 表中的字段,而根本不使用
PersonAttribute
表,但这只是说明问题的一个示例。实际上,我有大量的自定义属性,这些属性对于不同的人记录而言千差万别,因此以这种方式进行操作是不切实际的。
我无法谈论MySQL,但是在PostgreSQL中,您可以使用tablefunc模块中的crosstab函数:
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
视图中放置了明确的列列表。我不知道隐式列列表的任何“自动透视”创建方式。
编辑:
对于 庞大的 列列表(假设总是text
键入)作为一种解决方法,我看到了这种修改很少的方法:
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(");");
结果:
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'
);
结果:
TABLE PersonAttributePivot;
personid | age | haircolor
----------+-----+-----------
1 | 27 |
2 | | Brown
(2 rows)
问题内容: 我的表包含以下列: 我想显示如下: 如您所见,我想将列与自定义列名成对显示。这对是列A和B,列C和D以及列C和D。 问题答案:
问题内容: 我有一个具有当前值和先前值的sql表。 我想比较它们,如果值有变化,请在下表中显示。 在SQL 2008中是否可以不循环每一列? 问题答案: 您可以使用取消透视数据: 请参阅带有演示的SQL Fiddle。 仅仅因为我喜欢使用 数据透视 功能,所以以下是同时使用 取消 数据透视 和 数据透视 功能来获取结果的版本: 参见带有演示的SQL Fiddle
问题内容: 我需要将列转换为行并获取其平均值。 例如,我有此表: 输出应为: 我该如何实现?感谢您的帮助。 问题答案: 如果您使用的是11G,则可以使用: 但是由于您不是,所以您可以伪造它。从本网站改编: 在这两种情况下,内部结构都将行转换为列。在10克中,您只需要自己做即可。在刚刚产生虚值的列表,这必须有足够的覆盖要转换为行(如果你真的有1000,你真的应该重新审视数据模型)的列数。这两个语句使
问题内容: 我在SQL Server 2008中具有下表: 我需要创建以下输出的查询: 列可以固定为[Mitarbeiter1]-[Mitarbeiter5],因为每个Filiale的行数不能超过5行。 非常感谢您的帮助! 问题答案: 使用SQL Server 2008,将Pivot和Rank函数组合在一起,可以为每个雇员数量提供理想的结果。首先,我们为每个分支中的每个员工分配一个ID,从每个新分
问题内容: 我有一个如下所示的表。我的问题是:如何将列转换为行?我正在使用Microsoft SQL Server 我需要像下面的操作 怎么做?谢谢 问题答案: 您的资料 询问 结果集
问题内容: 我有一个以下格式的表格 我想将其转换为以下格式 如何通过sql查询或sql服务器程序集实现此目的? 问题答案: 您可以完成。如果您知道已知的列数,则可以对值进行硬编码: 参见带有演示的SQL Fiddle 如果列数未知,则可以使用动态sql: 参见带有演示的SQL Fiddle 您甚至可以使用: