SQL Query linking tables, returning the earliest history from one table with the associated result - sql

I have two tables which I need to query. Let's call them table A, and table A_HISTORIES.
Each row from Table A, is linked to multiple rows in A_HISTORIES. What I want to do is to be able to link each row from table A with its earliest history from table A_HISTORIES so something like:-
SELECT A.*
A_HISTORIES.CREATED_DATE
FROM A, A_HISTORIES
WHERE A.ID = A_HISTORIES.A_ID
AND A_HISTORIES.ID = (SELECT max(id) keep (dense_rank first order by CREATED_DATE)
FROM A_HISTORIES)
However, this will only return the row from A/A_HISTORIES that has the earliest CREATED_DATE. Can anyone help me do this per row in A?
Thanks

How about something like this:
SELECT A.*
A_HISTORIES.CREATED_DATE
FROM A
INNER JOIN A_HISTORIES ON A.ID = A_HISTORIES.A_ID
INNER JOIN (SELECT A_ID, MAX(CREATE_DATE) AS max_create_date
FROM A_HISTORIES
GROUP BY A_ID) max_hist ON A_HISTORIES.A_ID = max_hist.A_ID
AND A_HISTORIES.ceate_date = max_create_date

Related

Inner join of table a and table b with selecting only one row of multiple in table b ( row with colum n = max value )

i am a total beginner in SQL. So i have two tables ( table a and table b )
table a holds people with unique IDs, table b holds multiple rows for each person of table a and also the persons ID ( for a possible join ) . the rows in table b are sorted by the columnn row_number.
How can i select all people but only the row of table b with the highest row_number ?
i hope you could somewhat understand me.
Cheers
If i got you right:
SELECT a.persons_ID
,b.rn
FROM A
INNER JOIN
(
SELECT MAX(row_number_column) AS rn
,persons_ID
FROM B
GROUP BY persons_ID
) sub
ON sub.persons_ID = A.persons_ID
The subselect in the inner joins groups your data of table B. So there will be just one row for each persons_ID - the row with the highest row_number_column.
Finally just a simple join on persons_ID.
If you don't need any other information than the person ID and the last row_number per person, then it is quite trivial. Let's call the first table person and the second visit:
select person_id,
max(row_number) max_row_number
from visit
group by person_id
If you need some other information from the first table, like person.name, then perform the join:
select person.person_id,
person.name,
max(visit.row_number) max_row_number
from person
inner join visit on visit.person_id = person.person_id
group by person.person_id,
person.name
If you need some other information from the second table, like visit.present, then modern databases support the row_number() window function (not to be confused with the column that you have):
select name,
base.row_number,
present
from (
select person.name,
row_number() over (partition by visit.person_id
order by visit.row_number desc) rn,
visit.row_number,
visit.present
from person
inner join visit on visit.person_id = person.person_id
) base
where rn = 1
NB: I would strongly advise to rename the column row_number to some other name, as row_number is an analytic function in many databases.

SQL Inner Join using Distinct and Order by Desc

table a.
Table b . I have two tables. Table A has over 8000+ records and continues to grow with time.
Table B has only 5 or so records and grows rarely but does grow sometimes.
I want to query Table A's last records where the Id for Table A matches for Table B. The problem is; I am getting all the rows from Table A. I just need the ones where Table A and B match once. These are unique Id's when a new row is inserted into table B and never get repeated.
Any help is most appreciated.
SELECT a.nshift,
a.loeeworkcellid,
b.loeeconfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM oeeworkcell a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
ORDER BY a.loeeworkcellid DESC
I am assuming you want to get the only the lastest (as you said) row from the TableA but JOIN giving you all the rows.You can use the Row_Number() to get the rownumber and then apply the join and filter it with the Where clause to select only the first row from the JOIN. So what you can try as below,
;WITH CTE
AS
(
SELECT * , ROW_NUMBER() OVER(PARTITION BY loeeconfigworkcellid ORDER BY loeeworkcellid desc) AS Rn
FROM oeeworkcell
)
SELECT a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM CTE a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
WHERE
a.Rn = 1
You need to group by your data and select only the data having the condition with min id.
SELECT a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
FROM oeeworkcell a
INNER JOIN dbo.oeeconfigworkcell b
ON a.loeeconfigworkcellid = b.loeeconfigworkcellid
group by
a.nshift,
a.loeeworkcellid,
b.loeecoonfigworkcellid,
b.loeescheduleid,
b.sdescription,
b.sshortname
having a.loeeworkcellid = min(a.loeeworkcellid)

Match two tables based on minimum dates efficiently

I have two tables one which contains quarterly data and one which contains daily data. I would like to join the two tables such that for each day in the daily data the quarterly data for that quarterly is selected and returned daily. I am working with Postgres 9.3.
The current query is as follows:
select
a.ID,
a.datadate,
b.*,
case when a.datadate = b.rdq then 1 else 0 end as VALID
from proj_data a, proj_rat b
where a.id = b.id
and b.rdq = (select min(rdq)
from proj_rat c
where a.id = c.id and a.datadate >= c.rdq);
But it is excruciatingly slow and I need to do this for several thousand IDs. Can anyone suggest a more efficient solution?
This eliminates the need for a subquery in the where clause
select
ID,
a.datadate,
b.*,
(a.datadate = b.rdq)::integer as VALID
from
proj_data a
inner join
(
select distinct on (id, rdq) *
from project_rat
order by id, rdq
) b using(id)
where a.datadate >= b.rdq;

SQL Query - Return rows from table A matching any row in table B

I am trying to write a query which uses a list of unique LOCATIONs obtained from a first query, as criteria to query rows from a second table.
For example:
SELECT
TABLE_A."LOCATION",
MIN(TABLE_A.WORKDATE) AS MIN_WORK_DATE
FROM
DB.TABLE_A
WHERE
MIN_WORK_DATE > '201201'
Then somehow:
SELECT
TABLE_B."LOCATION",
(other fields of interest)
FROM
DB.TABLE_B
WHERE
TABLE_B."LOCATION" (is contained in the result above)
Thanks in advance for any help!
You can do it with join:
SELECT
b.location,
(other fields of interest)
FROM
tableB b
JOIN
(SELECT a.location, min(a.workdate) as min_workdate
FROM tableA a
GROUP BY a.location) c
ON b.location = c.location
WHERE c.min_workdate > '201201'
Fiddle
You can match any table's column with any another table's column:
EX:
SELECT
TABLE_A."LOCATION",
TABLE_A.WORKDATE AS WORK_DATE
FROM
DB.TABLE_A, DB.TABLE_B
WHERE
TABLE_A.SOME_COLUMN > 'some_value_given' and TABLE_A.SOME_COLUMN=TABLE_B.SOME_COULMN

Rewrite SQL and use of group by

I have written below sql for one of the requirement and is fetching my results. But, I am wondering if there is any better way of writing this query rather than using alias table as A.
SELECT A.*,B.OPRDEFNDESC FROM
( select OPRID_ENTERED_BY ,COUNT(*)
from ps_req_hdr
where entered_dt > '01-JUL-2012'
GROUP BY OPRID_ENTERED_BY
ORDER BY COUNT(*) DESC) A, PSOPRDEFN B
WHERE A.OPRID_ENTERED_BY=B.OPRID
You may be able to use a simple INNER JOIN to do the same thing...
SELECT A.OPRID_ENTERED_BY, COUNT(*), B.OPRDEFNDESC
FROM ps_req_hdr A
JOIN PSOPRDEFN B ON A.OPRID_ENTERED_BY = B.OPRID
WHERE A.entered_dt > '01-JUL-2012'
GROUP BY A.OPRID_ENTERED_BY, B.OPRDEFNDESC
ORDER BY COUNT(*) DESC
NOTE
As per the comments below, the COUNT(*) result for this query will NOT include records that don't have corresponding matches in table B, and it will inflate for non-unique matches in table B. What this means is: if B.OPRID is not a unique field or if A.OPRID_ENTERED_BY is not a foreign key for B.OPRID then this answer will not yield the same results as the original query.