SQL Server:从同一个表和不同表中获取日期时使用其他东西而不是联合

Posted

技术标签:

【中文标题】SQL Server:从同一个表和不同表中获取日期时使用其他东西而不是联合【英文标题】:SQL Server : use other thing instead of union when date fetch from same table and different table 【发布时间】:2018-08-02 08:05:43 【问题描述】:

我使用union 来组合表格中的选定数据。从同一个表中选择的所有数据但在每个select 中,查询选择了一些不同的列。

表架构:

   EID     name      x1       x2       x3
--------|--------|--------|--------|--------
   int    string   float    float    float

样本数据:

小样

  EID   name    x1     x2     x3
------|------|------|------|------
  110   Tom     2      3      5
  110   John    4      3      6
  110   Sam     1      2      3

查询:

select 
    name, 'x1' as title, x1 as result
from
    Sampletbl
where 
    EID = 110

union

select 
    name, 'x2' as title, x2 as result
from 
    Sampletbl
where 
    EID = 110

union

select 
    name, 'x3' as title, x3 as result
from
    Sampletbl
where 
    EID = 110

输出结果应如下所示:

 name   title   result  
------|-------|------
 Tom     x1      2      
 Tom     x1      3      
 Tom     x1      5      
 John    x2      4      
 John    x2      4      
 John    x2      6      
 Sam     x3      1      
 Sam     x3      2      
 Sam     x3      3      

问题:不使用unionunion all 获取数据的更好方法是什么?

使用的 DBMS 是 SQL Server 2008 R2,但我可以升级到 SQL Server 2014 或更高版本。

更新

原始表有数百万行。每个选择从表中读取数据。 每行都是唯一的,列有数据。 (可为空=假) 我想要提高性能的方法,但我无法更改结果选择的结构。

【问题讨论】:

定义“更好”。您遇到了什么问题? @iamdave 查询很慢,因为表有数百万条记录,并且每次都减少了选择和读取数据。 (我假设每个name 的预期输出应该只有一个x1 行,x2x3 也是如此,而不是您当前显示的内容,因为这是您的查询当前将产生的结果) 【参考方案1】:

您可以尝试将CROSS APPLYVALUES 一起使用

SELECT v.*
FROM T
CROSS APPLY (VALUES (name, 'x1',x1),
                    (name, 'x2',x2),
                    (name, 'x3',x3)
            ) 
            v (name, title,result )
order by title

[结果]

|  name | title | result |
|-------|-------|--------|
|   Tom |    x1 |      2 |
| John  |    x1 |      4 |
|   Sam |    x1 |      1 |
|   Sam |    x2 |      2 |
| John  |    x2 |      3 |
|   Tom |    x2 |      3 |
|   Tom |    x3 |      5 |
| John  |    x3 |      6 |
|   Sam |    x3 |      3 |

sqlfiddle

【讨论】:

【参考方案2】:

它叫UNPIVOT

declare @t table (EID int, name varchar(13), x1 float, x2 float, x3 float)
insert into @t(EID,name,x1,x2,x3) values
(110,'Tom ',2,3,5),
(110,'John',4,3,6),
(110,'Sam ',1,2,3)

select
    *
from
    @t
    unpivot (
        result for title in (x1,x2,x3)) u

结果:

EID         name          result                 title
----------- ------------- ---------------------- -----
110         Tom           2                      x1
110         Tom           3                      x2
110         Tom           5                      x3
110         John          4                      x1
110         John          3                      x2
110         John          6                      x3
110         Sam           1                      x1
110         Sam           2                      x2
110         Sam           3                      x3

如果您的所有输出行都将不同(从检查当前查询来看,我希望这是正确的),那么对当前查询的转换也会更快,干扰更少 - 使用 UNION ALL 而不是比UNIONUNION 被指定为删除重复项,如果您的输出包含大量行,这可能会占处理时间的很大一部分。

【讨论】:

表有 20 列,所有列都有数据。每条记录都是唯一的 union all 是否优于 cross applyunpivot @AmirAbdollahi- 如果您想对现有查询进行最小的更改,我只会建议 union all。如果UNPIVOT 对您正常工作(暂时忽略性能),我建议您这样做,因为语义,这就是您正在做的事情。所以告诉服务器你想要什么,然后它会尽力做到最好。如果UNPIVOT 表现不佳,是时候检查执行计划,看看是否缺少索引等。

以上是关于SQL Server:从同一个表和不同表中获取日期时使用其他东西而不是联合的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 从当前日期计算天数,不包括另一个表中的天数

SQL从日期范围内的同一表中的不同记录中获取多个项目的总和(ORACLE)

使用 SQL Server 从多个表中获取期初余额

如何从 SQL Server 中的表中获取行的索引?

如何获取在 SQL Server 内部数据库的不同表中重复的列[重复]

SQL Server merge用法