Return 1 result with left join from table B - sql

Table A Table B Table B Table B
Itemnr Itemnr Item Status Remark
100000 100000 1 Approved
200000 100000 2 Use up
100000 3 Obsolete
200000 1 Approved
200000 2 Use up
200000 3 Obsolete
I would like to see only one result per line in table A item with as result the Remark based on Item status 1. I tried a lot with the option of a left join but without the good result.

Is this what you want?
select a.itemnr, b.remark
from tablea a
inner join tableb b on b.itemnr = a.itemnr and b.item_status = 1
If some records in tablea might not have a corresponding row in tableb with item_status = 1 and you want to keep these in the resultset, then you can use left join instead of inner join.

For the data example you have provided, you don't need tablea:
select b.itemnr, b.remark
from tableb b
where b.item_status = 1;
You specify that you want a left join, which implies rows in tablea that are not in tableb, although you have no such examples in the question. In that case:
select a.itemnr, b.remark
from tablea a left join
tableb b
on b.itemnr = a.itemnr and b.item_status = 1;

You can use row_number()
select t.*
from (select a.*, b.*, row_number() over (partition by a.itemr order by b.status) as seq
from a inner join
b
on a.itemr = b.itemr
) t
where seq = 1;
This will return rows total itemrs along with first status. Also this assumes Itemnr, Item Status, Remark are the columns name.
EDIT : If you want to check, first status 1 is available or not then you can do :
SELECT a.itemr, b.remark
FROM a LEFT JOIN
b
ON b.itemr = a.itemr AND b.status = 1;

Related

Joining two tables where id does not equal

I'm struggling getting this query to produce the results I want.
I have:
table1, columns=empid, alt_id
table2, columns=empid, alt_id
I want to get the empid, and alt_id from table 1 where the alt_id does not match the alt_id in table2. They will both have alt_id numbers I just want to get the ones that do not match.
Any ideas?
SELECT * FROM table1
INNER JOIN table2 ON table2.empid = table1.empid AND table2.alt_id <> table1.alt_id
What does that really mean though? Normally when this is asked, it is of the form "I want all rows from A that have no row matching in B and all in B that have no match in A"
Which looks like this:
SELECT * FROM
A
FULL OUTER JOIN
B
ON
a.id = b.id
You'll see a null for any row data where there isn't a matching row on the other side:
A.id
1
2
B.id
1
3
Result of full outer join:
A.id B.id
1 1
2 null
null 3
You, however have asked for A-B join where the IDs aren't equal, which would be the more useless query of:
SELECT * FROM
A
INNER JOIN
B
ON
a.id != b.id
And it would look like:
A.id B.id
1 3
2 1
2 3
You seem to want not exists:
select t1.*
from table1 t1
where not exists (select 1 from table2 t2 where t2.alt_id = t1.alt_id);
It is unclear whether or not you also want to join on empid, so you might really want:
select t1.*
from table1 t1
where not exists (select 1 from table2 t2 where t2.alt_id = t1.alt_id and t2.empid = t1.empid);
A left join will find all records in Table A that do not match those in Table B. Then use a Where filter to find the Nulls from Table B. That will give you all those in Table A that do not have a matching ID in Table B.
Select A.*
from Table A
Left Join
Table B
on a.altid = b.altid
where b.altid is null;
select *
from [Login] L inner join Employee E
on l.EmployeeID = e.EmployeeID
where l.EmployeeID not in (select EmployeeID from Employee)

SQL: group function is not allowed here

I have this query
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID AND COUNT(B.*) < 4
WHERE A.STATUS = 0
In tablea, ID will have 2 row of data(2 entries), but in tableb the same ID will have upto 4 rows of data. I am trying to get the ID that has less than 4 rows of data in tableb and display that result.
so if ID 12345 is having only 2 rows of data in tableb, display that result. IF ID 98765 has 4 rows of data in tableb, ignore this entry.
But when i try the above query it says "group function is not allowed here". Please can someone help.
You can not use count() without goup by or having clause. In your case you need having
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID
WHERE A.STATUS = 0
having COUNT(B.*) < 4
see the sqlfiddle
write it the way you would say it...
"I am trying to get the ID that has less than 4 rows of data in tableb and display that result"
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
it's not clear, but if you also only want Ids which have 2 or more rows in TableA:
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
and (Select count(*) from TABLEA
where id = a.Id) > 1

Select all from one table and count from another and include nulls

I'm trying to get all ids from one table and a count of transactions from another table. The trick is that an id may not be listed in the transaction table. In that case, I want the query to return 0 for that id. (I apologize for the bad formatting)
ID Table
ID
1
2
3
Trans Table
ID Trans
1 123
1 234
3 345
3 456
3 567
Query results
ID - Trans Count
1 2
2 0
3 3
I have this code, but it just isn't working for me and I can't figure out why.
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
A.CURRENT_FLAG = 1
GROUP BY A.ID
When using left join, conditions on the first table go in the where clause. Conditions on the second table go in the on clause:
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A LEFT JOIN
B
ON A.ID = B.ID AND
B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
WHERE A.CURRENT_FLAG = 1
GROUP BY A.ID;
I would check if the value is null if then just replace it with a 0
The NVL Function will work perfect for this scenario.
SELECT A.ID, COUNT (NVL(B.TRANS,0)) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND A.CURRENT_FLAG = 1
GROUP BY A.ID

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]

Need to retrieve all records in table A and only single one in table B that is the last updated

I have to retrieve certain records in TABLE_A - then need to display the last time the row was updated - which is in TABLE_B (however, there are many records that correlate in TABLE_B). TABLE_A's TABLE_A.PK is ID and links to TABLE_B through TABLE_B.LINK, where the schema would be:
TABLE_A
===================
ID NUMBER
DESC VARCHAR2
TABLE_B
===================
ID NUMBER
LINK NUMBER
LAST_DATE DATE
And the actual table data would be:
TABLE_A
===================
100 DESCRIPTION0
101 DESCRIPTION1
TABLE_B
===================
1 100 12/12/2012
2 100 12/13/2012
3 100 12/14/2013
4 101 12/12/2012
5 101 12/13/2012
6 101 12/14/2013
So, I would need something to read out:
Result
====================
100 DESCRIPTION0 12/14/2013
101 DESCRIPTION1 12/14/2013
I tried to join different ways, but nothing seems to work:
select * from
(SELECT ID, DESC from TABLE_A WHERE ID >= 100) TBL_A
full outer join
(select LAST_DATE from TABLE_B WHERE ROWNUM = 1 order by LAST_DATE DESC) TBL_B
on TBL_A.ID = TBL_B.LINK;
The easiest thing to do would be to join table_a with an aggregate query on table_b:
SELECT table_a.*, table_b.last_date
FROM table_a
LEFT JOIN (SELECT link, MAX(last_date) AS last_date
FROM table_b
GROUP BY link) table_b ON table_a.id = table_b.link
If you just want the most recent date, think aggregation and join. The extra levels of subqueries do not help. Something like:
select a.id, a.desc, max(last_date)
from table_a a join
table_b b
on a.id = b.link
where a.id >= 100
group by a.id, a.desc;
Note: I doubt a full outer join is necessary, although you can keep that if you have join keys that don't match between the tables. Perhaps a left join is appropriate.
I should point out that if you want more fields from b, then your initial inclination to use row_number() is correct. But the query would look like:
select a.id, a.desc, max(last_date)
from table_a a left join
(select b.*, row_number() over (partition by link order by last_date desc) as seqnum
from table_b b
) b
on a.id = b.link and b.seqnum = 1
where a.id >= 100
group by a.id, a.desc;