繁体   English   中英

SQL。 如何比较值并从两个表中比较,并报告每行结果

[英]SQL. how to compare values and from two table, and report per-row results

我有两个桌子。 表A

id  name    Size
===================
1   Apple   7
2   Orange  15 
3   Banana  22
4   Kiwi    2
5   Melon   28
6   Peach   9

和表B

id  size
==============
1   14
2   5 
3   31
4   9
5   1
6   16
7   7
8   25

我的期望的结果将是(添加一列于表A,这是在表B具有尺寸尺寸小于表A的行数)

id  name    Size   Num.smaller.in.B
==============================
1   Apple   7      2
2   Orange  15     5
3   Banana  22     6
4   Kiwi    2      1
5   Melon   28     7
6   Peach   9      3  

表A和B都非常大。 有一个聪明的办法做到这一点。 谢谢

使用此查询很有帮助

SELECT id,
name,
Size,
(Select count(*) From TableB Where TableB.size<Size)
FROM TableA

获得结果的标准方法涉及非等联接,这将是Explain中的产品联接。 首先复制20,000行,然后进行7,000,000 * 20,000比较,并在计数之前有一个庞大的中间假脱机。

有一种基于OLAP功能的解决方案,通常效率很高:

SELECT dt.*,
   -- Do a cumulative count of the rows of table #2
   -- sorted by size, i.e. count number of rows with a size #2 less size #1   
   Sum(CASE WHEN NAME = '' THEN 1 ELSE 0 end)
   Over (ORDER BY SIZE, NAME DESC ROWS Unbounded Preceding)
FROM
 ( -- mix the rows of both tables, an empty name indicates rows from table #2
   SELECT id, name, size
   FROM a
   UNION ALL
   SELECT id, '', size
   FROM b
 ) AS dt
-- only return the rows of table #1
QUALIFY name <> '' 

如果表#2中有多行具有相同的大小,则最好在Union之前先进行计数以减小大小:

SELECT dt.*,
   -- Do a cumulative sum of the counts of table #2
   -- sorted by size, i.e. count number of rows with a size #2 less size #1   
   Sum(CASE WHEN NAME =''  THEN id ELSE 0 end)
   Over (ORDER BY SIZE, NAME DESC ROWS Unbounded Preceding)
FROM
 ( -- mix the rows of both tables, an empty name indicates rows from table #2
   SELECT id, name, size
   FROM a
   UNION ALL
   SELECT Count(*), '', SIZE
   FROM b
   GROUP BY SIZE
 ) AS dt
-- only return the rows of table #1
QUALIFY NAME <> ''

没有聪明的方法,您只需要像这样连接表:

select a.*, b.size
from TableA a join TableB b on a.id = b.id

为了提高性能,您需要在id列上具有索引。

也许

select 
  id,
  name,
  a.Size, 
  sum(cnt) as sum_cnt
from
  a inner join
  (select size, count(*) as cnt from b group by size) s on
  s.size < a.size
group by id,name,a.size

如果您正在使用大桌子。 索引表bsize字段可能会有所帮助。 我还假设表B的值是收敛的,除了要计算它们之外,还有很多重复的数据您不需要关心。

sqlfiddle

@Ritesh解决方案是完全正确的,另一个类似的解决方案是使用CROSS JOIN,如下所示

use tempdb
create table dbo.A (id int identity, name varchar(30), size int );
create table dbo.B (id int identity, size int);
go
insert into dbo.A (name, size)
values ('Apple',   7)
,('Orange',    15) 
,('Banana',  22)
,('Kiwi',    2 )
,('Melon',   28)
,('Peach',   6 )

insert into dbo.B (size)
values (14), (5),(31),(9),(1),(16), (7),(25)
go
-- using cross join
select a.*, t.cnt 
from dbo.A
cross apply (select cnt=count(*) from dbo.B where B.size < A.size) T(cnt)

试试这个查询

SELECT 
A.id,A.name,A.size,Count(B.size) 
from A,B 
where A.size>B.size 
group by A.size 
order by A.id;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM