Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a query for the following output?

Tags:

sql

sql-server

I have two tables Names and Name_ids as shown below.

Platform : SQL Server 2005/2008.

Names table:
    Nam                              ID
    -------------------------------- -----------
    A                                1
    B                                2
    C                                3
    D                                4
    E                                5
    F                                6
    G                                7
    H                                8

and

name_ids table

ID
-----------
3
6
8

I would like to produce following output joining these tables.

Nam                              Nam_ID      ID
-------------------------------- ----------- -----------
A                                1           NULL
B                                2           NULL
C                                3           3
D                                4           3
E                                5           3
F                                6           6
G                                7           6
H                                8           8

The logic is match the nam_id to id and if nam_id is less than any id then return NULL. If nam_id is greater than or equal to id, then return id. Here is the catch. In the above example, for F,6 we should not return F,6,3 combination but we should return only matching F,6,6. when a matching item is found like 6,6, it should skip other matches like 6,3. And after that use 7,6 and not 7,3. How do I write an sql query for the above? The query is time intensive and need to execute fast.

Scripts:
Create table Names(Nam nvarchar(32), ID int);

insert into names values('A', 1);
insert into names values('B', 2);
insert into names values('C', 3);
insert into names values('D', 4);
insert into names values('E', 5);
insert into names values('F', 6);
insert into names values('G', 7);
insert into names values('H', 8);


Create table name_ids( ID int);
insert into name_ids values(3);
insert into name_ids values(6);
insert into name_ids values(8);

Please help.

Update: I really appreciate your effort in providing solutions. Now I am confused to pick the best performing query. I have picked up few and trying to analyze the performance with very large result sets.

like image 938
fr21 Avatar asked Dec 20 '22 03:12

fr21


2 Answers

select n.Nam, 
CASE WHEN ni.ID IS NULL THEN (SELECT MAX(ID) from name_ids n1 where
                              n1.ID < n.ID)
                        ELSE  ni.ID
                        END
from Names n
left join name_ids ni on n.ID = ni.ID

SqlFiddle

like image 129
Raphaël Althaus Avatar answered Jan 07 '23 23:01

Raphaël Althaus


Please check my attempt:

SELECT 
    DISTINCT Nam, 
    a.ID Nam_ID, 
    MAX(b.ID) OVER (PARTITION BY Nam) ID
FROM 
    Names a LEFT JOIN name_ids b 
        ON a.ID>=b.ID
like image 41
TechDo Avatar answered Jan 08 '23 00:01

TechDo