SQL getting the last item by date - sql

I have a query that I had working on one item, then I wiped the dataset and started over and now I can't get it to pull any data at all.
The query is basically:
SELECT *
FROM TABLEA
LEFT JOIN TABLEB
ON TABLEA.ID = TABLEB.ID
WHERE TABLEA.ID = 1
AND TABLEB.DATE = (SELECT MAX(TABLEB.DATE)
FROM TABLEB
WHERE TABLEA.ID = 1)
TableB tracks changes and has hundreds of entries per ID. I want a single row of the last chronological item pertaining to that ID.
If there is a better way to do this then awesome but I'd really like to know why this specific query isn't working. When I run this query:
SELECT MAX(TABLEB.DATE)
FROM TABLEB
LEFT JOIN TABLEB
ON TABLEA.ID = TABLEB.ID
WHERE TABLEA.ID = 1
I get the proper value of the last date in the dataset.

select *
from tableA as a
left outer join tableB as b on b.ID = a.ID
where
b.Date = (select max(t.Date) from tableB as t WHERE t.ID = a.id)
-- and a.ID = 1 if you need it
if you just need date from tableB, you can do
select *
from tableA as a
left outer join (
select max(t.Date) as Date, t.ID from tableB as t group by t.ID
) as b on b.ID = a.ID
-- where a.ID = 1 if you need it
if you can use row_number function (you can change common table expression to subquery):
with cte as (
select *, row_number() over(partition by a.ID order by b.Date desc) as rn
from tableA as a
left outer join tableB as b on b.ID = a.ID
    -- where a.ID = 1 if you need it
)
select *
from cte
where rn = 1
if you're using SQL Server version >= 2005:
select *
from tableA as a
outer apply (
select top 1 t.*
from tableB as t
where t.ID = a.ID
order by t.Date desc
) as b
-- where a.ID = 1 if you need it
Please note using aliases in all subqueries.
About your initial query, I think you has an typo there:
SELECT *
FROM TABLEA
LEFT JOIN TABLEB
ON TABLEA.ID = TABLEB.ID
WHERE TABLEA.ID = 1
AND TABLEB.DATE = (SELECT MAX(TABLEB.DATE)
FROM TABLEB
WHERE TABLEA.ID = 1) -- <-- Do you mean TABLEB.ID = 1 ??

Here is one way:
SELECT *
FROM tableA LEFT JOIN
tableB
ON tableA.ID = tableB.ID
WHERE tableA.ID = 1
ORDER BY tableB.Date desc
LIMIT 1;

Related

SQL query to select from one table based on a column value in other table

I have two tables and I want to select all values from "TABLE A" that have a different value in a column from "TABLE B".
I tried this
SELECT A.* FROM tableA A
left join tableB B ON A.id = B.id WHERE B.column <> 1;
But this just return the value that I want to ignore.
SELECT A.*
FROM tableA A
INNER JOIN tableB B
ON A.id = B.id
WHERE B.column != 1;
or
SELECT A.* FROM tableA A WHERE A.Id NOT IN (SELECT B.Id FROM tableB B WHERE B.column != 1)
Depends on your SQL you can use <> or !=
I would suggest not exists:
SELECT A.*
FROM tableA A
WHERE NOT EXISTS (SELECT 1 FROM tableB B WHERE A.id = B.id AND B.column = 1);
Using a JOIN can result in duplicated rows, if more than one row in B matches the JOIN condition.

XOR JOIN in SQL

I have the following tables
Table A
ID "Other Columns"
1
2
3
Table B
ID "Other Columns"
3
4
5
What is the efficient way to return the below result?
Result
ID "Other Columns"
1
2
4
5
A full outer join should work, and only go through each table once. They can be tricky, so test carefully!
SELECT
isnull(A.ID, B.ID) ID
,"Other columns" -- Handle nulls properly!
from TableA A
full outer joing TableB B
on B.ID = A.ID
where not (A.ID is not null
and B.ID is not null)
You want to use left and right join and union them
Select TableA.ID as 'ID','Other Colums'
FROM TableA Left join TableB
ON TableA.ID=TableB.ID
WHERE TableB.ID IS NULL
UNION
Select TableB.ID as 'ID','Other Colums'
FROM TableA Right join TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IS NULL
You can try like this
SELECT
COALESCE(a.id, b.id),
OtherColumns
FROM #tablea a
FULL JOIN #tableb b
ON a.id = b.id
WHERE a.id IS NULL
OR b.id IS NULL
You can do this with a UNION ALL using a LEFT JOIN to determine if the ID is not in the other table. Keep in mind that the column count and datatypes between the two tables must match up:
Select A.Id, A.OtherColumns
From TableA A
Left Join TableB B On A.Id = B.Id
Where B.Id Is Null
Union All
Select B.Id, B.OtherColumns
From TableB B
Left Join TableA A On A.Id = B.Id
Where A.Id Is Null
Not quite sure what you need with the "Other columns", but you could use EXCEPT:
Select ID from TableA
EXCEPT
Select ID from TableB
If you need Other columns from TableA you could use:
Select ID, OtherColumn1, OtherColumn2 from TableA
where ID not in (select ID from TableB)
(as long as ID cannot be null in TableB)
I broke down each part to be clearer!
select *
into #temp
from
TabA Full outer join TabB
on TabA.ColNameA = TabB.ColNameB
select *
into #temp2
from #temp
where (ColNameA is Null Or ColNameB is null)
select ColNameA from #temp2
where ColNameA Is not null
union
select ColNameB from #temp2
where ColNameB Is not null

SQL full join priority

Say you have 3 tables (tableA, tableB, tableC), each with an ID column and a Value column. Some of the tables' IDs match but some don't.
If you do:
SELECT tableA.ID FROM tableA
FULL JOIN tableB ON (tableA.ID = tableB.ID)
FULL JOIN tableC ON (tableA.ID = tableC.ID)
Is this different from:
SELECT tableA.ID FROM tableA
FULL JOIN tableB ON (tableA.ID = tableB.ID)
FULL JOIN tableC ON (tableB.ID = tableC.ID)
Or:
SELECT Y.ID FROM
(SELECT tableA.ID FROM tableA
FULL JOIN tableB ON (tableA.ID = tableB.ID)) X
FULL JOIN tableC ON (X.ID = tableC.ID)) Y
??? Someone please explain if there is a difference. Thanks.
[Oracle SQL Developer version 4.02.15.21]
For starters, here are all 3 statements, syntactically cleaned up:
SELECT COALESCE(a.ID,b.ID,c.ID)
FROM tableA a
FULL JOIN tableB b ON a.ID = b.ID
FULL JOIN tableC c ON a.ID = c.ID
SELECT COALESCE(a.ID,b.ID,c.ID)
FROM tableA a
FULL JOIN tableB b ON a.ID = b.ID
FULL JOIN tableC c ON b.ID = c.ID
SELECT COALESCE(X.ID,c.ID)
FROM
( SELECT COALESCE(a.ID ,b.ID) ID
FROM tableA a
FULL JOIN tableB b ON a.ID = b.ID) X
FULL JOIN tableC c ON X.ID = c.ID
Surprisingly, the syntax of the first statement produces duplicate values, but statements 2 and 3 work as advertised.
Edit: Upon further testing, statements 1 and 2 are prone to duplicates, depending on which tables overlap. Statement 3 seems to be the only solid approach.
SQLFiddle

How to LEFT JOIN in DB2 iseries with first row?

I have need a query that JOIN a TABLE with A first row of other table value based:
SELECT * FROM TABLEA A LEFT JOIN
(SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
but DB2 return ERROR because can't use A.CODE
How can solve this?
You need to use the nested table expression:
SELECT * FROM TABLEA A LEFT JOIN
LATERAL (SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
This is a highly optimized statement.
Your not getting any data from tableb and your going for first row so you just need exists clause.
select a.* from tablea a
where exists (select * from tableb b
where a.fielda = b.fielda
and a.fieldb = b.fieldb
and b.code = a.code
and b.field2 = 'd' and b.field1 <> '3')
You can use the OLAP function row_number() to rank the records according to somefield(s) within a (fielda,fieldb,code) group. Somefield might be a transaction id, or sequence, for example. The order by clause is optional there, but without it, you might be randomly picking which record is the first in the group.
WITH B AS
(SELECT *,
row_number() over (partition by fielda,fieldb,code
order by somefield
) as pick
from TABLEB
WHERE FIELD1 <> '3'
and FIELD2 = 'D'
)
SELECT *
FROM TABLEA A LEFT JOIN B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
and A.CODE = B.CODE
where pick=1

Find Duplicates using Derived Tables Only

cte can be a memory hog sometimes. The following SQL works great until there are memory issues with other databases.
Any ideas how to reproduce Row_Number Over Partition using derived tables.
Table A holds the Work phone.
Table B holds the Id.
We have to join Table A with Table B in order to find duplicates in Table B; using the phone as the duplicate criteria.
This SQL works. I just want to see suggestions using derived tables instead.
;WITH cte
AS (SELECT Row_number() OVER (PARTITION BY a.WorkPhone ORDER BY b.id DESC ) AS
rownumber
,
a.WorkPhone,
a.id
FROM TableB B
JOIN TableA a
ON b.GroupofLeadsid = a.id
WHERE b.GroupofLeads = #GroupofLeads
AND NOT a.WorkPhone IS NULL
AND a.WorkPhone <> '')
UPDATE b
SET b.deleteflag = 1
FROM TableB b
JOIN cte t
ON b.id = t.id
WHERE b.GroupofLeads = #GroupofLeads
AND rownumber > 1
Update TableB
Set deleteflag = 1
From TableB As B
Join (
Select Row_Number() Over ( Partition By A.WorkPhone Order By B.Id Desc ) As RowNum
, A.WorkPhone, A.Id
, B.Id
From TableB As B1
Join TableA As A1
On A1.id = B1.GroupOfLeadsId
Where B1.GroupOfLeadsId = #GroupOfLeads
And A.WorkPhone <> ''
) As CTE
On CTE.Id = B.Id
Where CTE.RowNum > 1
Another choice:
Update TableB
Set deleteflag = 1
Where Exists (
Select 1
From (
Select Row_Number() Over ( Partition By A.WorkPhone Order By B.Id Desc ) As RowNum
, B.Id
From TableB As B1
Join TableA As A1
On A1.id = B1.GroupOfLeadsId
Where B1.GroupOfLeadsId = #GroupOfLeads
And A.WorkPhone <> ''
) As CTE
Where CTE.RowNum > 1
And CTE.Id = TableB.Id
)