Join two different columns from two different tables - sql-server-2005

i have two temporary table
Table 1
ID1 Name ID2 Single
----------------------------------------------------
1 ABC 1 100
2 DEF 1 200
Table 2
ID1 Name ID2 Monthly
----------------------------------------------------
3 PQR 2 500
4 LMN 2 600
I want Output
ID1 Name ID2 Single Monthly
--------------------------------------------------------
1 ABC 1 100 NULL
2 DEF 1 200 NULL
3 PQR 2 NULL 500
4 LMN 2 NULL 600
I used all Joins nothing working
thanks in advance

JOIN won't work for that case, you need to use UNION here:
SELECT ID1, NAME, ID2, Single, NULL FROM Table1
UNION ALL
SELECT ID1, NAME, ID2, NULL, Monthly FROM Table2

Just in case, for some mad reason, you really do need it as a JOIN rather than (as other's have pointed out) a UNION ALL:
create table #T1 (ID1 int,Name varchar(10),ID2 int,Single int)
insert into #T1 (ID1 , Name , ID2 , Single)
select 1 ,'ABC', 1 , 100 union all
select 2 ,'DEF', 1 , 200
create table #T2 (ID1 int,Name varchar(10),ID2 int,Monthly int)
insert into #T2 (ID1 , Name , ID2 , Monthly)
select 3 ,'PQR', 2 , 500 union all
select 4 ,'LMN', 2 , 600
select COALESCE(t1.ID1,t2.ID1) as ID1,COALESCE(t1.Name,t2.Name) as Name,
COALESCE(t1.ID2,T2.ID2) as ID2,t1.Single,t2.Monthly
from #T1 t1 full outer join #T2 t2 on 1=0
Gives the result you asked for

You don't need JOINS, you need a UNION (ALL).
UNION (Transact-SQL)
Combines the results of two or more queries into a single result set
that includes all the rows that belong to all queries in the union.
The UNION operation is different from using joins that combine columns
from two tables.
SQL Statement
SELECT ID1, Name, ID2, Single, NULL as Monthly
FROM Table1
UNION ALL
SELECT ID1, Name, ID2, Null, Monthly
FROM Table2

try to use UNION
SELECT * FROM Single
UNION
SELECT * FROM Monthly
Hope this helps.

Please use the following query...
Select
ID1,
Name,
ID2,
Single,
NULL AS 'Monthly"
from Table1
Union
Select
ID1,
Name,
ID2,
NULL AS 'Single',
Monthly
from Table2

Related

SQL query based on another table

I have tables like this:
table 1:
FNAME
ID1
FID
BREAD
XYZ
18BREAD
FISH
ABC
45FISH
BREAD_OLD
BNQ
18BREAD_OLD
BACON
TBG
77BACON
EGGS
CGS
99EGGS
BANANA
BHG
BANANA18
table 2:
FNAME
FID
BREAD
18
FISH
45
BACON
77
EGGS
99
currently a simple search is done on table 1 to find id's of food as follows:
SELECT ID1
FROM TABLE1
WHERE NAME IN NAME_LIST
so for example when the name list is: ('BREAD','FISH') then it returns XYZ, ABC. The problem is this misses 'BREAD_OLD' which is an older version with the same ID. (18)
I need to change this so now the search is done based on the FID of food rather than the NAME to find affected foods but I cannot change the input.
eg: given a list of foods: ('BREAD', 'FISH')
the result should be XYZ, ABC, BNQ (because BREAD matches 18 which matches BNQ in table 1)
how can this can be done? I think I need to use a join or do a 'select within a select' but I'm not sure how this would work with multiple inputs.
edit: ORACLE is the database
edit 2: adding BANANA18 to table 1, needs to be leading match
The correct solution would be to link on the FID fields. However, the FID field on table1 seems to concatenate the ID with the name. The solution would therfore be to extract the numeric value from that field and then use that to link it to the FID field on table 2. For example:
SELECT t1.FNAME, t1.ID1
FROM table1 t1
INNER JOIN table2 t2 ON t2.FID = regexp_replace(t1.FID, '^[^0-9]', '')
WHERE
t2.FNAME IN ('BREAD','FISH');
Assuming that table1.FID equals table2.FID concatenated with table1.FNAME then you do not need (slow) regular expressions and can use a simple equality combined with string concatenation:
SELECT t1.FNAME,
t1.ID1
FROM table1 t1
INNER JOIN table2 t2
ON t1.FID = t2.fid || t1.fname
WHERE t2.FNAME IN ('BREAD','FISH');
Which, for the sample data:
CREATE TABLE table1 (FNAME, ID1, FID) AS
SELECT 'BREAD', 'XYZ', '18BREAD' FROM DUAL UNION ALL
SELECT 'FISH', 'ABC', '45FISH' FROM DUAL UNION ALL
SELECT 'BREAD_OLD', 'BNQ', '18BREAD_OLD' FROM DUAL UNION ALL
SELECT 'BACON', 'TBG', '77BACON' FROM DUAL UNION ALL
SELECT 'EGGS', 'CGS', '99EGGS' FROM DUAL UNION ALL
SELECT 'BANANA', 'BHG', 'BANANA18' FROM DUAL UNION ALL
SELECT 'TOAST', 'TST', 'TOAST181' FROM DUAL;
CREATE TABLE table2 (FNAME, FID) AS
SELECT 'TOAST', 181 FROM DUAL UNION ALL
SELECT 'BREAD', 18 FROM DUAL UNION ALL
SELECT 'FISH', 45 FROM DUAL UNION ALL
SELECT 'BACON', 77 FROM DUAL UNION ALL
SELECT 'EGGS', 99 FROM DUAL;
Outputs:
FNAME
ID1
BREAD
XYZ
BREAD_OLD
BNQ
FISH
ABC
db<>fiddle here
Sample data:
SELECT * FROM TABLE1;
FNAME ID1 FID
-------------------------
BREAD XYZ 18BREAD
FISH ABC 45FISH
BACON TBG 77BACON
EGGS CGS 99EGGS
BREAD_OLD BNQ 18BREAD_OLD
SELECT * FROM TABLE2;
FNAME FID
----------
BREAD 18
FISH 45
BACON 77
EGGS 99
Query:
In query we join TABLE1 and TABLE2 on FID (using REGEX_SUBSTR to extract first n numbers of TABLE1 FID) so row 'BREAD_OLD' will be joined with row 'BREAD' from TABLE2 and when we add condition FNAME IN ('BREAD') both ID1 of 'BREAD' AND 'BREAD_OLD' will be selected.
SELECT ID1
FROM
(SELECT
TO_NUMBER(REGEXP_SUBSTR(FID,'^[0-9]{1,}'),'9999') AS FID,FNAME,ID1
FROM TABLE1)V
JOIN TABLE2 T
ON (V.FID=T.FID)
WHERE T.FNAME IN ('BREAD','FISH')
Result:
ID1
---
XYZ
ABC
BNQ
One option is joining the tables by matching concatenated columns of table2 with the extracted substrings upto _ character for fid column of table1 such as
SELECT id1
FROM table1 t1
JOIN table2 t2
ON REGEXP_SUBSTR(t1.fid,'[^_]+') = t2.fid||t2.fname
WHERE t2.fname IN ('BREAD','FISH')
Demo

Create a duplicate row on top of Select statement

table TEST
id
Name
1
abc
2
xyz
In general i used to get records from below query
Select id,name from TEST.
id
Name
1
abc
2
xyz
but now i want to create a duplicate for each row on top my select query
expected output: please suggest how can i achieve result like below
id
Name
1
abc
1
abc
2
xyz
2
xyz
You may cross join your table with a sequence table containing how ever many copies you want. Here is an example using an inline sequence table:
SELECT t1.id, t1.Name
FROM yourTable t1
CROSS JOIN (
SELECT 1 AS seq FROM dual UNION ALL
SELECT 2 FROM dual UNION ALL
SELECT 3 FROM dual
) t2
WHERE t2.seq <= 2
ORDER BY t1.id;
To me, UNION (ALL) set operator seems to be quite simple.
Sample data:
SQL> select * from test;
ID NAME
---------- ----
1 abc
2 xyz
UNION ALL:
SQL> select * from test
2 union all
3 select * from test;
ID NAME
---------- ----
1 abc
2 xyz
1 abc
2 xyz
SQL>
CREATE table test(
id integer,
name VARCHAR2(4)
);
INSERT into test (id, name) VALUES (1,'ABC');
INSERT into test (id, name) VALUES (2,'XYZ');
with data as (select level l from dual connect by level <= 2)
select *
from test, data
order by id, l
/
One more option is LATERAL
SELECT t.*
FROM test
, LATERAL (
SELECT id, name FROM DUAL
union all
SELECT id, name FROM DUAL
) t
One option is using a self-join along with ROW_NUMBER analytic function such as
WITH t AS
(
SELECT t1.id, t1.name, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY 0) AS rn
FROM test t1,
test t2
)
SELECT id, name
FROM t
WHERE rn <= 2
Demo

How to count distinct rows and get data of the row and count of it as a second column

Let's say I have a data
ID
AAA
ABB
ABC
BDS
BRD
CXD
DCU
ETS
I would like to count distinct to a first letter rows and get the number of their appearance to the right. Sorry I know I am not a very good user of a technical language, but I am new to SQL and English is not my first language.
So by script I would like to return
ID Total
A 3
B 2
C 1
D 1
E 1
I have tried
select left(id,1), count(left(id,1) as Total
from Places
group by Id
order by Total desc;
, but it didn't work. Your help will be greatly appreciated.
select left(id,1), count(*) as Total
from Places
group by left(id,1)
order by Total desc;
Is this you need?
declare #t table(val varchar(10))
insert into #t
select 'AAA' union all
select 'ABB' union all
select 'ABC' union all
select 'BDS' union all
select 'BRD' union all
select 'CXD' union all
select 'DCU' union all
select 'ETS'
select left(t1.val,1) as id ,count(t1.val) as total from #t as t1 left join
(
select distinct right(val,1) as val from #t
) as t2 on t1.val =t2.val
group by left(t1.val,1)
Result is
id total
---- -----------
A 3
B 2
C 1
D 1
E 1

How to select maximum value of two identical columns in same table?

id1 id2 name
1 1 2 a
2 3 4 b
3 5 6 c
4 7 8 d
5 9 10 e
select id1, id2, name
from Emp3
where id2 in (select MAX(id2) from Emp3)
How can I print only the maximum number?
USe
select id2
from Emp3
where id2 in (select MAX(id2) from Emp3)
This will print only 10
if you want the maximum among those 2 columns then use
SELECT
CASE
WHEN MAX(id1) >= MAX(id2) THEN MAX(id1)
WHEN MAX(id2) >= MAX(id1) THEN MAX(id2)
END AS MaxValue
FROM Emp3
Use TOP and ORDER BY to get the result
SELECT TOP 1 ID2 FROM Emp3 ORDER BY ID2 DESC
select max(id) from (
select max(id1) as id from Emp3
union
select max(id2) as id from Emp3
)
DECLARE #T TABLE (ID1 INT ,ID2 INT ,NAME VARCHAR(80))
INSERT INTO #T VALUES (1,2,'NME1')
INSERT INTO #T VALUES (3,4,'NME2')
INSERT INTO #T VALUES (5,6,'NME3')
INSERT INTO #T VALUES (7,8,'NME4')
INSERT INTO #T VALUES (9,10,'NME5')
INSERT INTO #T VALUES (11,12,'NME6')
SELECT * FROM #T
SELECT MAX(ID1) ID FROM
(
SELECT ID1 FROM #T T1
UNION
SELECT ID2 FROM #T T2
)TT
If both id columns are indexed, use derived table with UNION ALL:
select max(id)
from
(
select max(id1) as id from Emp3
union all
select max(id2) from Emp3
)
If they are not indexed, use CASE:
select max(case when id1 > id2 then id1
when id2 > id1 then id2
else coalesce(id1,id2) end)
from Emp3
This answer uses COALESCE to handle NULLs (if there are any...) The table will be read only once. (With the UNION solution the table will be read twice, and you don't want to do that without any index!)
Older answers:
I guess you want the row with the highest id1/id2 value?
Return a row when no other row with higher id value exists:
select id1, id2, name
from Emp3 e1
where not exists (select 1 from Emp3 e2
where e2.id1 > e1.id1
or e2.id1 > e1.id2
or e2.id2 > e1.id1
or e2.id2 > e1.id2)
Will return both rows if there's a tie. (Two or more rows with same highest value.)
Alternative solution, use TOP, combined with ORDER BY with CASE to find each rows larger id value:
select TOP 1 id1, id2, name
from Emp3
order by case when id1 > id2 then id1 else id2 end desc
Alternative 3, a sub-query with UNION ALL to find largest id:
select TOP 1 id1, id2, name
from Emp3
where (select max(case when id1 > id2 then id1 else id2 end) from Emp3) in (id1,id2)

How to select in SQL Server 2008

Have an issue
Examle
ID ID2
1 100
3 100
5 100
1 110
2 110
4 110
select * from table where ID in (1,4) ---executing not correctly
select * from table where ID = '1' and ID = '4' ---not work
I need that ID2 will '110' (select ID2 which have 2 value ID)
Thanks.
If you have few ID's you can use EXISTS:
SELECT ID, ID2
FROM dbo.Table1 t1
WHERE EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=1 AND t2.ID2=t1.ID2
)
AND EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=4 AND t2.ID2=t1.ID2
)
AND ID IN (1, 4)
This returns the two records that have the same ID2 and ID=1 AND ID=4.
ID ID2
1 110
4 110
Demo-Fiddle
SELECT ID FROM (
SELECT ID, COUNT(*) OVER(PARTITION BY ID2) as cnt FROM Table) t
WHERE t.cnt>1