2016-09-28 2 views
1

Ich habe zwei Tabellen. Tabelle ASQL. Wie man Werte und aus zwei Tabellen vergleicht, und pro Zeile Ergebnisse meldet

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

Und Tabelle B

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

My gewünschtes Ergebnis wird sein (eine Spalte der Tabelle A hinzu, die die Anzahl der Zeilen in Tabelle B ist die Größe kleiner als haben Größe in Tabelle 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 

Beide Tabelle A und B sind ziemlich riesig. Gibt es einen cleveren Weg dies zu tun? Dank

+0

Was genau ist * ziemlich riesig *? Gibt es irgendeine Art von Gruppierung oder vergleicht es tatsächlich alle Zeilen? – dnoeth

+0

ist Pfirsich 6 oder 9 in Tabelle a? – Beth

+0

@Beth. soll 9. Entschuldigung wegen des Tippfehlers –

Antwort

3

Mit dieser Abfrage ist es hilfreich

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

Es gibt keine kluge Art und Weise, dies zu tun, müssen Sie nur die Tabellen wie folgt verbinden:

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

Leistung verbessern Sie Indizes für die ID-Spalten haben brauchen.

+0

Sorry, ich habe vergessen anzugeben. Lassen Sie mich klarstellen, ich möchte eine Spalte mit Informationen, die die [Anzahl der Zeilen in Tabelle B, die Größenwert kleiner als Größe in Tabelle A] haben –

+0

außer er will nicht auf ID beitreten, er ist auf Größe kleiner als Beitritt Größe in anderer Tabelle – Beth

0

@Ritesh Lösung vollkommen richtig ist, eine andere ähnliche Lösung ist mit CROSS unter

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) 
1

vielleicht

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 

, wenn Sie wie gezeigt JOIN arbeite mit großen Tabellen. Indextabelle b 's size Feld könnte helfen. Ich gehe auch davon aus, dass die Werte in der Tabelle B konvergieren, dass es viele Duplikate gibt, die Sie nicht interessieren, außer dass Sie sie zählen wollen.

sqlfiddle

0

Diese Abfrage

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; 
2

Der Standard Weg, um Ihr Ergebnis zu bekommen, beinhaltet nicht-Equi-Join, die ein Produkt beitreten wird in Erklären. Zunächst werden 20.000 Zeilen dupliziert, gefolgt von 7.000.000 * 20.000 Vergleichen und einer riesigen Zwischenspool vor der Zählung.

Es gibt eine Lösung auf Basis von OLAP-Funktionen, die in der Regel sehr effizient ist:

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

Wenn mehrere Zeilen mit der gleichen Größe in Tabelle # gibt es 2 Sie besser vor der Union zählen, um die Größe zu reduzieren:

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 <> '' 
Verwandte Themen