SQL joining on >= - sql

I have a table like this in ORACLE
a b
-- --
1000 1
100 2
10 3
1 4
My other table has numbers like '67' or '112' in a column called numbers for example.
How can I join to this table using those values and get the correct result where >=1000 would be 1 and >= 100 would be 2 >=10 would be 3 etc.
I tried to do a
select g.b
from table o
join table2 g on o.column >= g.a
when I do this say 1002 was the value of g I would get the back these results.
1
2
3
4
when I just want 1

Easiest would be if your lookup table had ranges instead of just one number, such as row 1 = 1000,9999,1 and row 2 = 100,999,2 etc.
Then your join might be
SELECT OtherTable.n, lookup.b
from OtherTable
LEFT JOIN lookup on OtherTable.n between lookup.low and lookup.high
But, if you really want to use your original table, then on SQL Server, do this:
/*CREATE TABLE #A (a int,b int)
INSERT INTO #A VALUES (1000,1),(100,2),(10,3),(1,4)
CREATE TABLE #B (n INT)
INSERT INTO #B VALUES (67),(112),(4),(2001)
*/
SELECT B.n, A1.b
FROM #B B OUTER APPLY (SELECT TOP 1 a,b FROM #A A WHERE A.a<B.n ORDER BY A.a DESC) A1

Here's one way to do it using a subquery to get the MAX of column a, and then rejoining on the same table to get b:
select t.numericvalue, t2.b
from (
select t.numericvalue, max(t2.a) maxb
from table1 t
join table2 t2 on t.numericvalue >= t2.a
group by numericvalue
) t join table2 t2 on t.maxb = t2.a
SQL Fiddle Demo

Related

Oracle SQL Update column with data from another table using three conditional statements

Scenario:
I have two separate tables (table 1 and table 2)
I want to update a column from table one with the value of a column from table 2
Case 1:
I need columns b,c and d in table 1 to match b,c and d in table 2 before the update occurs
Case 2:
Column b in table 1 has a true value but Column b in table two references a look up (example in table 1 column b may have a value of blue but in table 2 column b has the value 14567 which is the id in a lookup table that references blue)
How would you accomplish getting this update completed?
create table ta as
select 1 ID,'Alex' Name , 27 age from dual
union
select 2 ID,'Bob' Name , 32 age from dual;
create table tb as
select 1 ID,'Alex' Name , 29 age from dual
union
select 5 ID,'Dick' Name , 24 age from dual;
update ta a
set a.age = (select b.age from tb b where a.id=b.id and b.name=a.name)
where exists ( select 1 from tb where a.id=tb.id and a.name = tb.name);
Assuming table lookup has columns b (corresponding to t2.b) and col_x (corresponding to t1.b), you could do something like this, using the merge statement:
merge into t1
using (
select t2.a, l.col_x, t2.c, t2.d
from t2 join lookup l on t2.b = l.b
) s
on (t1.b = s.col_x and t1.c = t2.c and t1.d = t2.d)
when matched then update
set t1.a = s.a
;

TSQL select max from 3 columns and then inner join a column

How do I do this:
in table A I have 3 columns with integer values: a,b,c
in table B I have 3 columns with integer values: x,y,z
I want to select max of (a,b,c) and inner join the corresponding value from x,y,z.
Example:
a = 1, b = 2, c = 3
x = 7, y = 8, z = 9
result:
table with two columns
firstColumn | secondColumn
c | 9
explanation: c is the max of a,b,c and we take the name, not the value
9 is the value from the second table what we need
thanks in advance
ps I am using sql server 2014
Edit: I tried to make an example with excel table
Unless both tables have only 1 row you'll propably don't want to do a CROSS JOIN that would join all records from table1 to all from table2.
So my guess is that you're looking for something like this:
select
case
when c > isnull(a,0) and c > isnull(b,0) then 'c'
when b > isnull(a,0) then 'b'
when a is not null then 'a'
end as firstColumn,
case
when c > isnull(a,0) and c > isnull(b,0) then z
when b > isnull(a,0) then y
when a is not null then x
end as secondColumn
from table1 t1
join table2 t2 on t1.table2_id = t2.id
Just a bit of test data:
declare #table1 table (id int identity(1,1), a int, b int, c int, table2_id int default 1);
declare #table2 table (id int, x int, y int, z int);
insert into #table1 (a, b, c) values
(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1),
(4,5,5),(5,4,5),(5,5,4),(4,5,4),(4,4,5),(4,4,4),
(6,7,null),(6,null,7),(null,6,7),
(8,null,null),(null,8,null),(null,null,8),(null,null,null);
insert into #table2 (id, x, y, z) values (1,100,200,300);
The table structure you have shown us does not support your requirement. You need something that joins the rows in one table to the other.
If this exists you can then use (demo)
SELECT t1label,
t2col
FROM TableA TA
JOIN TableB TB
ON TA.rownum = TB.rownum
CROSS APPLY (SELECT TOP 1 *
FROM (VALUES('A', TA.a, TB.x),
('B', TA.b, TB.y),
('C', TA.c, TB.z)) v(t1label, t1col, t2col)
ORDER BY t1col DESC) CA
In the event a TableA row has two or more columns with the same maximum value it is undeterministic which will be selected.

select sql query to merge results

I have a table old_data and a table new_data. I want to write a select statement that gives me
Rows in old_data stay there
New rows in new_data get added to old_data
unique key is id so rows with id in new_data should update existing ones in old_data
I need to write a select statement that would give me old_data updated with new data and new data added to it.
Example:
Table a:
id count
1 2
2 19
3 4
Table b:
id count
2 22
5 7
I need a SELECT statement that gives me
id count
1 2
2 22
3 4
5 7
Based on your desired results:
SELECT
*
FROM
[TableB] AS B
UNION ALL
SELECT
*
FROM
[TableA] AS A
WHERE
A.id NOT IN (SELECT id FROM [TableB])
I think this would work pretty neatly with COALESCE:
SELECT a.id, COALESCE(b.count, a.count)
FROM a
FULL OUTER JOIN b
ON a.id = b.id
Note - if your RDBMS does not contain COALESCE, you can write out the function using CASE as follows:
SELECT a.id,
CASE WHEN b.count IS NULL THEN a.count
ELSE b.count END AS count
FROM ...
You can write a FULL OUTER JOIN as follows:
SELECT *
FROM a
LEFT JOIN b
ON a.id = b.id
UNION ALL
SELECT *
FROM b
LEFT a
ON b.id = a.id
You have to use UPSERT to update old data and add new data in Old_data table and select all rows from Old_data. Check following and let me know what you think about this query
UPDATE [old_data]
SET [count] = B.[count]
FROM [old_data] AS A
INNER JOIN [new_Data] AS B
ON A.[id] = B.[id]
INSERT INTO [old_data]
([id]
,[count])
SELECT A.[id]
,A.[count]
FROM [new_Data] AS A
LEFT JOIN [old_data] AS B
ON A.[id] = B.[id]
WHERE B.[id] IS NULL
SELECT *
FROM [old_data]

SQL Server - Providing priority to where clause condtions

Please consider the following SQL.
declare #t1 table(site int, id int, name varchar(2))
declare #t2 table(site int, id int, mark int)
insert into #t1
select 1,1,'A'
union select 1,2,'B'
union select 1,3,'C'
union select 2,2,'D'
union select 2,3,'C'
insert into #t2
select 1,1,10
union select 1,2,20
union select 0,3,30
union select 1,3,40
union select 2,3,40
union select 2,3,40
select distinct a.site, a.id,a.name,b.mark
from #t1 a
inner join #t2 b
on (a.site =b.site or b.site = 0) and a.id = b.id
where a.site=1
It produces the following result
site id name mark
----------------------------
1 1 A 10
1 2 B 20
1 3 C 30
1 3 C 40
It's correct.
But I want a person's data exactly once. The SQL should first check whether there is an entry for a person in #t2 for a specific site. If entry is found, then use it. If not, the mark of that person will be the person's mark who has the same name in site 0.
In this case, I want the result as follows.
site id name mark
----------------------------
1 1 A 10
1 2 B 20
1 3 C 40
But if (1,3,40) isn't in #t2, The result should be as follows.
site id name mark
----------------------------
1 1 A 10
1 2 B 20
1 3 C 30
How can I do this?
I can do it using Common Table Expression.
So please provide me a faster way.
I'll run it on about 100 millions rows.
You can roll all of the conditions into the on clause:
declare #target_site as Int = 1
select distinct a.site, a.id, a.name, b.mark
from #t1 as a inner join
#t2 as b on a.site = #target_site and a.id = b.id and
( a.site = b.site or ( b.site = 0 and not exists ( select 42 from #t2 where site = #target_site and id = a.id ) ) )
Outer Join to the t2 table twice, and Use a subquery to ensure that only records that have a match or are zeroes are included.
Select distinct a.site, a.id, a.name,
coalesce(sm.mark, zs.mark) mark
from #t1 a
Left Join #t2 sm -- for site match
on sm.id = a.id
And sm.site = a.site
Left Join #t2 zs -- for zero site
on zs.id = a.id
And zs.site = 0
Where Exists (Select * From #t2
Where id = a.id
And Site In (a.Site, 0))
And a.site=1

Problem combining result of two different queries into one

I have two tables (TableA and TableB).
create table TableA
(A int null)
create table TableB
(B int null)
insert into TableA
(A) values (1)
insert into TableB
(B) values (2)
I cant join them together but still I would like to show the result from them as one row.
Now I can make select like this:
select
(select A from tableA) as A
, B from TableB
Result:
A B
1 2
But if I now delete from tableB:
delete tableB
Now when I run the same query as before:
select
(select A from tableA) as A
, B from TableB
I see this:
A B
But I was expecting seeing value from tableA
like this:
Expected Result:
A B
1
Why is this happening and how can I still see the value from TableA although selectB is returning 0 rows?
I am using MS SQL Server 2005.
Use a LEFT JOIN (although it's more of a cross join in your case).
If your db supports it:
SELECT a.a, b.b
FROM a
CROSS JOIN b
If not, do something like:
SELECT a.a, b.b
FROM a
LEFT JOIN b ON ( 1=1 )
However, once you have more rows in a or b, this will return the cartesian product:
1 1
1 2
2 1
2 2
This will actually give you what you're looking for, but if you only have one row per table:
select
(select A from tableA) as A
, (select B from TableB) as B
give this a try:
DECLARE #TableA table (A int null)
DECLARE #TableB table (B int null)
insert into #TableA (A) values (1)
insert into #TableB (B) values (2)
--this assumes that you don't have a Numbers table, and generates one on the fly with up to 500 rows, you can increase or decrease as necessary, or just join in your Numbers table instead
;WITH Digits AS
(
SELECT 0 AS nbr
UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
)
, AllNumbers AS
(
SELECT u3.nbr * 100 + u2.nbr * 10 + u1.nbr + 1 AS Number
FROM Digits u1, Digits u2, Digits u3
WHERE u3.nbr * 100 + u2.nbr * 10 + u1.nbr + 1 <= 500
)
, AllRowsA AS
(
SELECT
A, ROW_NUMBER() OVER (ORDER BY A) AS RowNumber
FROM #TableA
)
, AllRowsB AS
(
SELECT
B, ROW_NUMBER() OVER (ORDER BY B) AS RowNumber
FROM #TableB
)
SELECT
a.A,b.B
FROM AllNumbers n
LEFT OUTER JOIN AllRowsA a on n.Number=a.RowNumber
LEFT OUTER JOIN AllRowsB b on n.Number=b.RowNumber
WHERE a.A IS NOT NULL OR b.B IS NOT NULL
OUTPUT:
A B
----------- -----------
1 2
(1 row(s) affected)
if you DELETE #TableB, the output is:
A B
----------- -----------
1 NULL
(1 row(s) affected)
try this:
select a, (select b from b) from a
union
select b, (select a from a) from b
should retrieve you all the existing data.
you can filter it more by surrounding it with another select