[英]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
如果您正在使用大桌子。 索引表b
的size
字段可能会有所帮助。 我还假设表B
的值是收敛的,除了要计算它们之外,还有很多重复的数据您不需要关心。
@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.