记录集横向显示输出即交叉表的两种方法

本文介绍了三种在 SQL Server 中实现数据转置的方法,包括使用 DataTable 对象进行转置、通过存储过程直接处理以及创建通用存储过程来生成交叉表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:

 

城市

 

 

 

 

员工人数

成都10
深圳8
北京9
上海3
大连

6

 


横向

城市成都深圳北京上海大连
员工人数108936



      DataTable dtNew = new DataTable();
        dtNew.Columns.Add("ColumnName", typeof(string));
        for (int i = 0; i < dt.Rows.Count; i++)
       {
            dtNew.Columns.Add("Column" + (i + 1).ToString(), typeof(string));
       }
        foreach (DataColumn dc in dt.Columns)
        {
            DataRow drNew = dtNew.NewRow();
            drNew["ColumnName"] = dc.ColumnName;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                drNew[i + 1] = dt.Rows[i][dc].ToString();
            }
            dtNew.Rows.Add(drNew);
        }


经过上面的语句,您的dt就已经成功转置了,你可以直接用它作为datagrid 或者gridview的数据源。

 

 

方法二,直接在存储过程中转换

 

 

 

存储过程中如何将sql查询结果集横向显示出,谢谢,即

字段1   字段2           显示成:       1       2       3         4         5
1               1                                     1       2       3         4         5  
2               2
3               3
4               4
5               5

下面是偶的一个输出交叉表的存储过程,比较通用
//******************************************************************
CREATE   procedure   CorssTab  
@strTabName   as   varchar(50)   =   'Employees ',   --此处放表名
@strCol   as   varchar(50)   =   'City ',   --表头分组依据字段
@strGroup   as   varchar(50)   =   'TitleOfCourtesy ',--分组字段
@strNumber   as   varchar(50)   =   'ReportsTo ',   --被统计的字段
@strSum   as   varchar(10)   =   'Sum '   --运算方式
AS

DECLARE   @strSql   as   varchar(1000),   @strTmpCol   as   varchar(100)
EXECUTE   ( 'DECLARE   corss_cursor   CURSOR   FOR   SELECT   DISTINCT   '   +   @strCol   +   '   from   '   +   @strTabName   +   '   for   read   only   ')   --生成游标

begin
SET   nocount   ON  
SET   @strsql   = 'select   '   +   @strGroup   +   ',   '   +   @strSum   +   '( '   +   @strNumber   +   ')   AS   [ '   +   @strSum   +   '   of   '   +   @strNumber   +   '] '   --查询的前半段

OPEN   corss_cursor
while   (0=0)
BEGIN
FETCH   NEXT   FROM   corss_cursor   --遍历游标,将列头信息放入变量@strTmpCol
INTO   @strTmpCol
if   (@@fetch_status <> 0)   break
SET   @strsql   =   @strsql   +   ',   '   +   @strSum   +   '(CASE   '   +   @strCol   +   '   WHEN   ' ' '   +   @strTmpCol   +   ' ' '   THEN   '   +   @strNumber   +   '   ELSE   Null   END)   AS   [ '   +   @strTmpCol   +   '   '   +   @strCol   +   '] '   --构造查询
END
SET   @strsql   =   @strsql   +   '   from   '   +   @strTabname   +   '   group   by   '   +   @strGroup   --查询结尾

EXECUTE(@strsql)   --执行


IF   @@error   <> 0   RETURN   @@error   --如果出错,返回错误代码
CLOSE   corss_cursor  
DEALLOCATE   corss_cursor   RETURN   0   --释放游标,返回0表示成功

end
GO

 

 

 

同样是存储过程的方法三:

 

生成交叉表的简单通用存储过程

-
-
create proc p_qry
@TableName sysname, --表名
@纵轴 sysname, --交叉表最左面的列
@横轴 sysname, --交叉表最上面的列
@表体内容 sysname, --交叉表的数数据字段
@条件 varchar(1000),--查询的处理条件
@是否加横向合计 bit, --为1时在交叉表横向最右边加横向合计
@是否加纵向合计 bit --为1时在交叉表纵向最下边加纵向合计
as
declare @s nvarchar(4000),@sql varchar(8000)

--规范条件


--判断横向字段是否大于纵向字段数目,如果是,则交换纵横字段

--生成交叉表处理语句
set @s='
set @s=''''
select @s=@s+'',[''+cast(['+@横轴+'] as varchar)+'']=sum(case ['+@横轴
+'] when ''''''+cast(['+@横轴+'] as varchar)+'''''' then ['+@表体内容+'] else 0 end)''
from ['+@TableName+']
'+@条件+'
group by ['+@横轴+']'
exec sp_executesql @s
,N'@s varchar(8000) out'
,@sql out

--是否生成合计字段的处理
declare @sum1 varchar(200),@sum2 varchar(200),@sum3 varchar(200)
select @sum1=case @是否加横向合计
when 1 then ',[合计]=sum(['+@表体内容+'])'
else '' end
,@sum2=case @是否加纵向合计
when 1 then '['+@纵轴+']=case grouping(['
+@纵轴+']) when 1 then ''合计'' else cast(['
+@纵轴+'] as varchar) end'
else '['+@纵轴+']' end
,@sum3=case @是否加纵向合计
when 1 then ' with rollup'
else '' end

--生成交叉表
exec('select '+@sum2+@sql +@sum1+'
from ['+@TableName+']
'+@条件+'
group by ['+@纵轴+']'+@sum3)


////////////////////////////////////////////////////////////////
调用语句

exec   p_qry   'student1','name','subject','source','sum',0,0
exec   p_qry   'student1','name','subject','source','sum',1,1

 


////////////////////////////////////////////////////

 

 

 

 


文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/7_databases/sql/sqlServer/20100721/473614.html

 

<think>好的,用户现在问的是如何在SQL中联接来自两个不同表的查询结果。首先,我需要确认用户的具体需求是什么。他们可能是在处理需要合并两个表数据的情况,比如可能是想组合两个表的行,或者根据某些条件关联两个表的列。 用户之前的问题是关于在SSMS中调整小数位数显示,现在转向了表的联接,这可能意味着他们在处理数据整合或报表生成的任务。我需要考虑用户可能的背景,他们可能已经有一定的SQL基础,但需要更深入的指导。 接下来,我需要回忆SQL中联接表的不同方法。常见的联接类型包括INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN,还有UNION操作。用户的问题中提到“联接来自两个不同表的查询结果”,这里的“联接”可能有歧义,是横向联接(即JOIN)还是纵向合并(即UNION)?需要进一步分析用户的意图。 假设用户是想将两个表的行合并,比如两个结构相同的表上下堆叠,那么应该使用UNION或UNION ALL。但如果用户是想根据某些列的值关联两个表的列,那么应该使用JOIN操作。需要看用户的具体需求,但可能需要覆盖这两种情况。 在之前的回答中,用户提到了SSMS的使用,所以可能需要给出具体的SQL示例,并说明如何在SSMS中执行这些查询。同时,用户可能需要知道不同方法的区别和适用场景,比如UNION会去重而UNION ALL不会,或者不同类型的JOIN如何影响结果集。 另外,需要注意用户可能遇到的常见问题,比如联接条件不明确导致笛卡尔积,或者数据类型不匹配导致UNION失败。要提醒用户注意这些点,并提供解决方案,比如使用ON子句明确联接条件,或确保UNION的列数据类型一致。 还需要考虑性能问题,比如JOIN时的索引使用,或者UNION ALL比UNION更快,因为不需要去重。这些信息对用户可能有帮助,尤其是在处理大数据量时。 最后,要确保回答结构清晰,分点说明不同的方法,并给出示例和注意事项。可能需要比较不同方法的优缺点,帮助用户根据实际情况选择合适的方法。同时,使用中文,避免技术术语过于复杂,保持解释的易懂性。</think>--- 在 SQL 中联接两个不同表的查询结果,主要通过 **表连接(JOIN)** 或 **集合操作(UNION)** 实现。以下是具体方法和场景说明: --- ### 一、横向联接(合并列) **适用场景**:将两个表的列按关联条件横向拼接 **核心语法**:使用 `JOIN` + `ON` 子句 #### 1. **内连接(INNER JOIN)** ```sql SELECT A.column1, B.column2 FROM TableA A INNER JOIN TableB B ON A.key = B.key; ``` - **特点**:仅返回两个表匹配成功的记录 - **示意图**: ![INNER JOIN](https://www.w3schools.com/sql/img_innerjoin.gif) (交集部分) #### 2. **左连接(LEFT JOIN)** ```sql SELECT A.column1, B.column2 FROM TableA A LEFT JOIN TableB B ON A.key = B.key; ``` - **特点**:返回左表全部记录 + 右表匹配记录(未匹配则填充 `NULL`) - **典型用途**:统计主表数据时附带关联信息(如订单表关联用户表) #### 3. **全外连接(FULL OUTER JOIN)** ```sql SELECT A.column1, B.column2 FROM TableA A FULL OUTER JOIN TableB B ON A.key = B.key; ``` - **特点**:返回两个表所有记录(未匹配部分填充 `NULL`) --- ### 二、纵向合并(合并行) **适用场景**:将两个表结构相同的数据上下堆叠 **核心语法**:使用 `UNION` 或 `UNION ALL` #### 1. **去重合并(UNION)** ```sql SELECT column1, column2 FROM TableA UNION SELECT column1, column2 FROM TableB; ``` - **特点**:自动去重,性能较低(需排序对比) #### 2. **全量合并(UNION ALL)** ```sql SELECT column1, column2 FROM TableA UNION ALL SELECT column1, column2 FROM TableB; ``` - **特点**:保留所有重复记录,性能更高 --- ### 三、特殊场景技巧 #### 1. **自连接(SELF JOIN)** ```sql SELECT A.employee_name, B.manager_name FROM Employees A LEFT JOIN Employees B ON A.manager_id = B.employee_id; ``` #### 2. **交叉连接(CROSS JOIN)** ```sql SELECT A.color, B.size FROM Colors A CROSS JOIN Sizes B; ``` - **特点**:生成笛卡尔积(所有组合) #### 3. **带条件的复杂连接** ```sql SELECT A.order_id, B.product_name FROM Orders A INNER JOIN Products B ON A.product_id = B.product_id AND A.order_date > '2023-01-01'; ``` --- ### 四、性能优化要点 1. **索引优化**:确保 `JOIN` 使用的字段已建立索引 2. **字段选择**:避免 `SELECT *`,明确列出所需字段 3. **过滤前置**:在 `JOIN` 前先用 `WHERE` 缩小数据集 4. **执行计划**:通过 SSMS 的 `显示估计的执行计划`(快捷键 `Ctrl+L`)分析瓶颈 --- ### 五、SSMS 操作演示 1. **编写查询**:在查询窗口中输入 SQL 代码 2. **调试技巧**: - 分步执行(逐步添加 `JOIN` 条件) - 使用 `TOP 10` 快速测试 3. **结果验证**:在结果网格中检查拼接后的数据完整性 --- ### 六、常见错误排查 | 错误现象 | 解决方案 | |--------------------------|----------------------------------| | 列名歧义(如重复列名) | 使用表别名明确来源:`A.column` | | 数据类型不匹配 | 用 `CAST` 统一类型 | | 笛卡尔积爆炸(百万行) | 检查是否漏写 `ON` 条件 | | `NULL` 值导致连接丢失 | 改用 `COALESCE()` 处理空值 | --- ### 七、实战案例 **需求**:合并订单表(Orders)和退货表(Returns),显示所有订单及退货状态 ```sql SELECT O.order_id, O.order_date, R.return_reason, CASE WHEN R.return_id IS NULL THEN '正常' ELSE '已退货' END AS status FROM Orders O LEFT JOIN Returns R ON O.order_id = R.order_id; ``` --- 掌握这些方法后,您可以根据实际需求选择最适合的数据联接方式。如果遇到具体场景问题,可提供表结构和样例数据,我会给出针对性优化建议!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值