sql多表行转列、级联行转列示例代码

背景介绍

随着互联网的普及,数据处理变得越来越重要。在处理数据时,我们常常需要将多表行转列并进行级联操作。本文将详细介绍SQL中多表行转列和级联行转列的实现方法以及示例代码。

多表行转列

基本概念和实现方法

多表行转列是指将不同表的行数据转为列数据并合并在一起,常用于表间关联查询,让查询结果更加清晰和直观。实现多表行转列的方法最常见的是使用SQL的Pivot语句。

SELECT [column1], [column2], [column n...],

pivoted_column1, pivoted_column2, pivoted_column n...

FROM

( SELECT [grouping_column], [column], [value] FROM [table] ) [p]

PIVOT

( [aggregate_function]([value])

FOR [column] IN ( pivoted_column1, pivoted_column2, pivoted_column n...) ) AS [alias];

例如,我们有两个表,一个为订单表,其中包含订单编号、客户姓名、订单日期和订单金额;另外一个表为商品表,包含商品编号、商品名称和商品价格。如果我们要在一个查询中显示某客户的所有订单和订单中商品的名称和价格,则可以使用下面的SQL语句:

SELECT CustomerName, OrderDate, ProductName, Price

FROM

(SELECT o.OrderID, o.OrderDate, c.CustomerName, od.ProductID, od.UnitPrice

FROM Orders o

INNER JOIN Customers c ON o.CustomerID = c.CustomerID

INNER JOIN OrderDetails od ON od.OrderID = o.OrderID) AS SourceTable

INNER JOIN Products p ON SourceTable.ProductID = p.ProductID

WHERE CustomerName = 'John Smith'

ORDER BY OrderDate;

当查询结果集较大时,上述SQL语句就显得较为臃肿。这时,我们可以使用Pivot语句,将商品的名称和价格分别转为Product1和Price1、Product2和Price2......Productn和Pricen列,形成更为直观的结果集。

SELECT OrderDate, Product1, Price1, Product2, Price2, ... Productn, Pricen

FROM

(SELECT o.OrderID, o.OrderDate, p.ProductName, od.UnitPrice,

'Product'+CAST(ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY p.ProductID) AS VARCHAR) AS ProdCol,

'Price'+CAST(ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY p.ProductID) AS VARCHAR) AS PriceCol

FROM Orders o

INNER JOIN Customers c ON o.CustomerID = c.CustomerID

INNER JOIN OrderDetails od ON od.OrderID = o.OrderID

INNER JOIN Products p ON p.ProductID = od.ProductID) AS SourceTable

PIVOT

(MIN(ProductName) FOR ProdCol IN (Product1, Product2, ... Productn)) AS PivotTable1

PIVOT

(MIN(UnitPrice) FOR PriceCol IN (Price1, Price2, ... Pricen)) AS PivotTable2

WHERE OrderDate >= '2005-01-01' AND CustomerName = 'John Smith'

ORDER BY OrderDate, OrderID;

上述SQL语句将Product和Price字段所在的子查询的输出数据集按照OrderID和按照ProductID排列,并且将每个子查询的结果通过Pivot函数进行转置,生成一个动态的结果集。

示例代码

下面是一个简单的示例,用于说明如何使用Pivot语句实现多表行转列:

/* 创建订单表 */

CREATE TABLE Orders (

OrderID INT PRIMARY KEY,

OrderDate DATE,

CustomerID INT,

Amount DECIMAL(10, 2)

);

/* 向订单表中插入数据 */

INSERT INTO Orders (OrderID, OrderDate, CustomerID, Amount)

VALUES (1, '2020-01-01', 1001, 100.00),

(2, '2020-02-01', 1002, 200.00),

(3, '2020-03-01', 1003, 300.00),

(4, '2020-04-01', 1001, 400.00),

(5, '2020-05-01', 1002, 500.00),

(6, '2020-06-01', 1003, 600.00);

/* 创建客户表 */

CREATE TABLE Customers (

CustomerID INT PRIMARY KEY,

CustomerName VARCHAR(50)

);

/* 向客户表中插入数据 */

INSERT INTO Customers (CustomerID, CustomerName)

VALUES (1001, 'John Smith'),

(1002, 'Mary Brown'),

(1003, 'David Johnson');

/* 创建订单详情表 */

CREATE TABLE OrderDetails (

DetailID INT PRIMARY KEY,

OrderID INT,

ProductID INT,

UnitPrice DECIMAL(10, 2),

Quantity INT

);

/* 向订单详情表中插入数据 */

INSERT INTO OrderDetails (DetailID, OrderID, ProductID, UnitPrice, Quantity)

VALUES (1, 1, 1, 10.00, 2),

(2, 1, 2, 20.00, 3),

(3, 2, 2, 20.00, 4),

(4, 2, 3, 30.00, 1),

(5, 3, 1, 10.00, 3),

(6, 4, 2, 20.00, 5),

(7, 5, 1, 10.00, 4),

(8, 6, 3, 30.00, 2);

/* 创建商品表 */

CREATE TABLE Products (

ProductID INT PRIMARY KEY,

ProductName VARCHAR(50),

Price DECIMAL(10, 2)

);

/* 向商品表中插入数据 */

INSERT INTO Products (ProductID, ProductName, Price)

VALUES (1, 'Product A', 10.00),

(2, 'Product B', 20.00),

(3, 'Product C', 30.00);

/* 使用Pivot语句实现多表行转列 */

SELECT CustomerName, OrderDate, Product1, Price1, Product2, Price2, Product3, Price3

FROM

(SELECT o.OrderID, o.OrderDate, c.CustomerName, od.ProductID, od.UnitPrice,

'Product'+CAST(ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY p.ProductID) AS VARCHAR) AS ProdCol,

'Price'+CAST(ROW_NUMBER() OVER(PARTITION BY o.OrderID ORDER BY p.ProductID) AS VARCHAR) AS PriceCol

FROM Orders o

INNER JOIN Customers c ON o.CustomerID = c.CustomerID

INNER JOIN OrderDetails od ON od.OrderID = o.OrderID

INNER JOIN Products p ON p.ProductID = od.ProductID) AS SourceTable

PIVOT

(MIN(ProductName) FOR ProdCol IN (Product1, Product2, Product3)) AS PivotTable1

PIVOT

(MIN(UnitPrice) FOR PriceCol IN (Price1, Price2, Price3)) AS PivotTable2

ORDER BY CustomerName, OrderDate;

级联行转列

基本概念和实现方法

级联行转列是指将关联表中的数据和行转为列,并形成一个动态的结果集。实现级联行转列的方法最常见的是使用SQL的Unpivot语句。

SELECT [columns], [unpivoted_column], [unpivoted_value]

FROM [table]

UNPIVOT

([unpivoted_value] FOR [unpivoted_column] IN([column1],[column2],...,[column n])) AS [alias];

例如,我们有一个数据表,其中包含员工姓名、工资、住址和出生日期等信息,但这些信息存储在多个列中。如果我们想将这些信息展示在同一行中,则可以使用Unpivot语句。下面的示例用于展示如何使用Unpivot语句来将基础数据转换为新的格式:

SELECT FirstName, LastName, Attribute, Value

FROM Employee

UNPIVOT

(Value FOR Attribute IN (Salary, Address, BirthDate)) AS UnpivotTable;

上述SQL语句将Employee表中包含的属性(Salary, Address, BirthDate)作为列名,将这些列中的值作为新表中的一列,并同时保留该行中的其他信息(FirstName, LastName)。

示例代码

下面是一个简单的示例,用于说明如何使用Unpivot语句实现级联行转列:

/* 创建员工表 */

CREATE TABLE Employee (

EmployeeID INT PRIMARY KEY,

FirstName VARCHAR(50),

LastName VARCHAR(50),

Salary DECIMAL(10, 2),

Address VARCHAR(200),

BirthDate DATE

);

/* 向员工表中插入数据 */

INSERT INTO Employee (EmployeeID, FirstName, LastName, Salary, Address, BirthDate)

VALUES (1, 'John', 'Smith', 10000.00, 'No.1, Road A, City X', '1990-01-01'),

(2, 'Mary', 'Brown', 20000.00, 'No.2, Road B, City Y', '1995-01-01'),

(3, 'David', 'Johnson', 30000.00, 'No.3, Road C, City Z', '2000-01-01');

/* 使用Unpivot语句实现级联行转列 */

SELECT EmployeeID, Attribute, Value

FROM Employee

UNPIVOT

(Value FOR Attribute IN (Salary, Address, BirthDate)) AS UnpivotTable;

总结

本文详细介绍了SQL中多表行转列和级联行转列的实现方法和示例代码。多表行转列是指将不同表的行数据转为列数据并合并在一起,常用于表间关联查询,让查询结果更加清晰和直观。实现多表行转列的方法最常见的是使用SQL的Pivot语句。级联行转列是指将关联表中的数据和行转为列,并形成一个动态的结果集。实现级联行转列的方法最常见的是使用SQL的Unpivot语句。同时,本文还为每个转置操作提供了相应的示例代码,读者可以根据自己的需求进行参考和使用。

数据库标签