SQL。如何比较两个 table 的值,并报告每行结果

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

我有两个 Table。 table一个

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

和TableB

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

我想要的结果是(向 Table A 添加一列,这是 Table B 中 size 小于的行数尺寸 Table 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  

Table A 和 B 都很大。有没有聪明的方法来做到这一点。谢谢

没有什么聪明的方法可以做到这一点,您只需要像这样连接表格:

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

要提高性能,您需要在 id 列上建立索引。

使用这个查询很有帮助

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

@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 
  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

如果您使用的是大型 tables。索引 table bsize 字段可能会有所帮助。我还假设 table B 中的值收敛,除了你想计算它们之外,还有许多你不关心的重复项。

sqlfiddle

试试这个查询

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;

获得结果的标准方法涉及非等值连接,这将是 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 <> '' 

如果 table 中有多个相同大小的行 #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 <> ''