Get Records By Most Recent Date From two tables - sql

I have two SQL tables. Each has an ID with other columns and a Date.
Is there a way that I can get the result from these two tables in one query sorted by the date? For example, as a result, I may have one record from table 1 followed by two records from table 2 and then another record from table one and so on. I have tried the code below but I think that I am not on the right track.
I would appreciate your help.
SELECT
app.ID as 'AppraisalID',
app.CityName,
app.CountryName,
app.Street,
app.DateCreated,
subApp.ID as 'SubAppraisalID',
subApp.Message,
subApp.DateCreated
From
(
SELECT TOP 10
dbo.Appraisal.ID,
dbo.Appraisal.Street,
dbo.Country.Name as 'CountryName',
dbo.City.Name as 'CityName',
dbo.Appraisal.DateCreated
FROM dbo.Appraisal
INNER JOIN dbo.Country ON dbo.Appraisal.CountryID = dbo.Country.ID
INNER JOIN dbo.City ON dbo.Appraisal.CityID = dbo.City.ID
Order by dbo.Appraisal.DateCreated DESC
) app
Cross Join
(
SELECT TOP 10
dbo.Sub_Appraisal.ID,
dbo.Sub_Appraisal.Message,
dbo.Sub_Appraisal.DateCreated
FROM dbo.Sub_Appraisal
Order by dbo.Sub_Appraisal.DateCreated DESC
) subApp
Order By
app.DateCreated DESC,
subApp.DateCreated DESC
Thanks guys.

What you want to use is the UNION operator, although the column lists for each table (or at least the ones that you are selecting) must match up. You'll want to make sure that you do the ordering after the UNION.
A simplified example:
SELECT
col1,
col2,
some_date
FROM
(
SELECT
col1,
col2,
some_date
FROM
Table1
UNION ALL
SELECT
col1,
col2,
some_date
FROM
Table2
) AS SQ
ORDER BY
some_date

Look at union all. You'll need to make sure that your result columns are the same data type.
select a.id "id", null "message", a.cityname "city", a.countryname "country", a.street "street", a.datecreated "dt"
from dbo.appraisal a
union all
select s.id, s.message, null, null, null, s.datecreated
from dbo.sub_appraisal s
order by 6
However, I suspect that your sub_appraisal table is missing an ID linking it to the appraisal table. This is how you would ideally join the two tables allowing you to accurately get the data out, in the correct order because you cannot guarantee that sub_appraisal records are created directly after appraisal records and before another appraisal record is created. If this happened, your query would give you results you're possibly not expecting.

Related

Retrieve records from a table which has different partial key

I have a table like as follows:
Table 1 Schema
ID/Name/Description are part of primary key.
Table Structure with data
Now, I want to compare table records on the basis of ID and need to find records which are not matching. for e.g. from above screen print I want last row as my query result.
I will be really thankful for any input. Thanks !
select t1.*
from
table t1
join
(
select name,description,comment
from
table t2
group by
name,description,comment
having count(*)=1) b
on t1.name=b.name
and t1.description=b.description
and t1.comment=b.comment
If using SQLServer,this does the trick..
SELECT TOP 1 WITH TIES ID,NAME,DESCRIPTION,COMMENT
FROM
#TEMP
ORDER BY
COUNT(ID) OVER (PARTITION BY NAME,DESCRIPTION,COMMENT )

SQL Server : UNION ALL but remove duplicate IDs by choosing first date of occurrence

I am unioning two queries but I'm getting an ID that occurs in each query. I do not know how to keep only the first time the id occurs. Everything else about the row is different. In general, it will be hard to know which of the two queries I will have to keep a duplicate on, therefore, I need a general solution.
I was thinking about creating a temp table and choosing the min date (once the date has been converted to an int).
Any ideas on the proper syntax?
You can do this using the row_number() function. This will assign a sequential number, starting with 1, to each row with the same id (based on the partition by clause). The ordering of the sequence is determined by the order by clause. So, the following assigns 1 to the earliest date for each id:
select t.*
from (select t.*,
row_number() over (partition by id order by date asc) as seqnum
from ((select *
from <subquery1>
) union all
(select *
from <subquery2>
)
) t
) t
where seqnum = 1;
The final where clause simply filters for the first occurrence.
If you use the keyword UNION, then it will remove duplicates from the two data sets you are working with. UNION ALL preserves duplicates.
You can view the specifics here:
http://www.w3schools.com/sql/sql_union.asp
If you want to only have one of the 2 records and they are not identical you will have to filter them yourself. You may need to do something like the following. THis may be possible to do with the one (select union select) block but this should get you started.
select *
from (
select id
, date
, otherstuf
from table_1
union all
select id
, date
, otherstuf
from table_2
) x1
, (
select id
, date
, otherstuf
from table_1
union all
select id
, date
, otherstuf
from table_2
) x2
where x1.id = x2.id
and x1.date < x2.date
Although rethinking this if you go down a path like this why bother to UNION it?

Implement FIRST() in select and not in WHERE

I want to get first value in a field in Oracle when another corresponding field has max value.
Normally, we would do this using a query and a subquery. The subquery ordering by a field and the outer query with where rownum<=1.
But, I cannot do this because the table aliases persist only one level deep and this query is a part of another big query and I need to use some aliases from the outermost query.
Here's the query structure
select
(
select a --This should get first value of a after b's are sorted desc
from
(
select a,b from table1 where table1.ID=t2.ID order by b desc
)
where rownum<=1
)
) as "A",
ID
from
table2 t2
Now this is not gonna work because alias t2 wont be available at innermost query.
Real world analogy that comes to my mind is I have a table containing records for all employees of a company, their salaries(including past salaries) and the date from which the salary was effective. So, for each employee, there will multiple records. Now, I want to get latest salaries for all the employees.
With SQL server, I could have used SELECT TOP. But that's not available with Oracle and since where clauses execute before order by, I cannot use where rownum<=1 and order by in same query and expect correct results.
How do I do this?
Using your analogy of employees and their salaries, if I understand what you are trying to do, you could do something like this (haven't tested):
SELECT *
FROM (
SELECT employee_id,
salary,
effective_date,
ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY effective_date DESC) rowno
FROM employees
)
WHERE rowno=1
I would much rather see you connect the subquery up with a JOIN instead of embedding it in the SELECT. Cleaner SQL. Then you can use the windowing function that roartechs suggests.
Select t2.whatever, t1.a
From table2 t2
Inner Join (
Select tfirst.ID, tfirst.a
From (
Select ID, a,
ROW_NUMBER() Over (Partition BY ID ORDER BY b DESC) rownumber
FROM table1
) tfirst
WHERE tfirst.rownumber=1
) t1 on t2.ID=t1.ID

Create a UNION query that identifies which table the unique data came from

I have two tables with data. Both tables have a CUSTOMER_ID column (which is numeric). I am trying to get a list of all the unique values for CUSTOMER_ID and know whether or not the CUSTOMER_ID exists in both tables or just one (and which one).
I can easily get a list of the unique CUSTOMER_ID:
SELECT tblOne.CUSTOMER_ID
FROM tblOne.CUSTOMER_ID
UNION
SELECT tblTwo.CUSTOMER_ID
FROM tblTwo.CUSTOMER_ID
I can't do just add an identifier column to the SELECT statemtn (like: SELECT tblOne.CUSTOMER_ID, "Table1" AS DataSource) because then the records wouldn't be unique and it will get both sets of data.
I feel I need to add it somewhere else in this query but am not sure how.
Edit for clarity:
For the union query output I need an additional column that can tell me if the unique value I am seeing exists in: (1) both tables, (2) table one, or (3) table two.
If the CUSTOMER_ID appears in both tables then we'll have to arbitrarily pick which table to call the source. The following query uses "tblOne" as the [SourceTable] in that case:
SELECT
CUSTOMER_ID,
MIN(Source) AS SourceTable,
COUNT(*) AS TableCount
FROM
(
SELECT DISTINCT
CUSTOMER_ID,
"tblOne" AS Source
FROM tblOne
UNION ALL
SELECT DISTINCT
CUSTOMER_ID,
"tblTwo" AS Source
FROM tblTwo
)
GROUP BY CUSTOMER_ID
Gord Thompson's answer is correct. But, it is not necessary to do a distinct in the subqueries. And, you can return a single column with the information you are looking for:
select customer_id,
iif(min(which) = max(which), min(which), "both") as DataSource
from (select customer_id, "tblone" as which
from tblOne
UNION ALL
select customer_id, "tbltwo" as which
from tblTwo
) t
group by customer_id
We could add an identifier column with the integer data type and then do an outer query:
SELECT
CUSTOMER_ID,
sum(Table)
FROM
(
SELECT
DISTINCT CUSTOMER_ID,
1 AS Table
FROM tblOne
UNION
SELECT
DISTINCT CUSTOMER_ID,
2 AS Table
FROM tblTwo
)
GROUP BY CUSTOMER_ID`
So if the "sum is 1" then it comes from tablOne and if it is 2 then it comes from tableTwo an if it is 3 then it exists in both
If you want to add a 3rd table in the union then give it a value of 4 so that you should have a unique sum for each combination

How to do a query that is agnostic of the sort field?

I have multiple tables that have the same date_time added field in each table. After doing a UNION of all tables i want to sort them by the most recent one. But the query will tell me that the i have to add a table name like videos.date_time rather than ORDER BY date_time. How can i structure the query so that it is agnostic of the which date_time field?
Unless you are using a proprietary feature such as SQL Server's TOP directive, the Order By in a Union query is always at the bottom and always applies to the entire query. E.g.
Select Col1, date_time
From Table1
Union All
Select Col1, date_time
From Table2
Order By date_time
If your query does include various elements such TOP or LIMIT which require an Order By and thus you want to differentiate the Order By's, then you can encapsulate your query into a derived table:
Select Col, date_time
From (
Select Col1 As Col, date_time
From Table1
Union All
Select Col1, date_time
From Table2
) As Z
Order By Z.date_time
In SQL Server you can also order by a column number, e.g. "ORDER BY 2" in which case whatever the second column is in your union set would be the sort target.
As I understand you have X tables (where X is > 1), and every table have it's own date_time column and you want to get last updated. If that's true, than one of the possible ways is to do it that way
SELECT id, date_added FROM table1
UNION ALL
SELECT id, date_added FROM table2
ORDER BY date_added DESC;
Other ways which I have in mind is when you fetch results, put them in array and do the "magic" inside it.