Add condition in SQL query with INNER JOIN on ROW_NUMBER - sql

I'm trying to write an INNER JOIN with ROW_NUMBER but the result of my query is not what i expected.
I'm trying to adapt this query :
SELECT TOP 5 *
FROM Details, Application
WHERE Application.ID = Details.ApplicationID
AND Details.ApplicationID = 5
with ROW_NUMBER().
I used this example How to do an inner join on row number in sql server
Now I have this :
SELECT TOP 5 *
FROM
(SELECT *, ROW_NUMBER() OVER(ORDER BY Details.ID) AS RowNum
FROM Details) A
JOIN
(SELECT *, ROW_NUMBER() OVER(ORDER BY Application.ID) AS RowNum
FROM Application) B ON A.RowNum = B.RowNum AND A.RowNum BETWEEN 1 AND 5
But I'm trying to add this condition
WHERE
Application.ID = Details.ApplicationID
AND Details.ApplicationID = 5
inside my new query, can someone give me some help please?
Can I add a WHERE inside my query?
PS: I'm using SQL Server 2008

MySQL has a direct analogue to SQL Server's TOP; it is LIMIT, and it behaves the same way:
SELECT *
FROM Details d
INNER JOIN Application a
ON a.ID = d.ApplicationID AND d.ApplicationID = 5
ORDER BY some_col
LIMIT 5;
Note that it doesn't make much sense to use LIMIT (or TOP) without an ORDER BY clause. This is because you haven't told the database which order you want to use when choosing the first 5 records.
Also, I converted your implicit old-school join to a modern, explicit, inner join. This is the preferred way of writing joins now.

Related

Limit number of rows fetching in a left outer join in Oracle

I'm going to create a data model in oracle fusion applications. I need to create column End_date based on two tables in the query. So I used two methods.
Using a subquery:
SELECT *
FROM (SELECT projects_A.end_date
FROM projects_A, projects_B
WHERE projects_A.p_id = projects_B.p_id
AND rownum = 1)
Using a LEFT OUTER JOIN:
SELECT projects_A.end_date
FROM projects_A
LEFT JOIN projects_B
ON projects_A.p_id = projects_B.p_id
WHERE rownum = 1
Here when I used a subquery, the query returns the results as expected. But when I use left outer join with WHERE rownum = 1 the result is zero. Without WHERE rownum = 1 it retrieves all the results. But I want only the first result. So how can I do that using left outer join? Thank you.
Looks like you want to bring a non-null end_date value(So, add NULLS LAST), but the sorting order is not determined yet(you might add a DESC to the end of the ORDER BY clause depending on this fact ), and use FETCH clause(the DB version is 12c+ as understood from the comment) with ONLY option to exclude ties as yo want to bring only single row.
So, you can use the following query :
SELECT A.end_date
FROM projects_A A
LEFT JOIN projects_B B
ON A.p_id = B.p_id
ORDER BY end_date NULLS LAST
FETCH FIRST 1 ROW ONLY

Can we select first row of data from column in sql?

I have a table with multiple data for same ID. I want to get the first row data for the ID.
I have added the below SQL that I have tried.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
LEFT OUTER JOIN "client_details" ON ("client"."id" = "client_details"."client_id")
Since I have multiple address for the same ID, can we get only the first id?
Currently the output I get is 2 rows with different addresses.
You can add to your SQL LIMIT 1 and in case you want to be sure the order you can also add to your SQL ORDER BY...
You can use distinct on:
select distinct on (c.id) c.id, c.company_name, cd.address
from Client c left join
client_details cd
on c.id = cd.client_id
order by c.id, ?;
The ? is for the column that specifies the ordering (the definition of "first"). I am guessing that cd.id is what you want.
Note that this query removes the double quotes and introduces table aliases. This is easier on both the eyes (to read) and the fingers (to type).
use row_number()
select * from
(
SELECT
"client"."id",
"client"."company_name",
"client_details"."address",row_number() over(partition by "client"."id" order by "client_details"."address") as rn
from Client
LEFT OUTER JOIN "client_details" ON "client"."id" = "client_details"."client_id"
)A where rn=1
If there is a field you can order the results by you could use a lateral join e.g.
SELECT
"client"."id",
"client"."company_name",
"client_details"."address"
from Client
left join lateral (
select *
from client_details cd
where cd.client_id = client.id
order by [some_ordering_field]
limit 1
) "client_details" on true

SQL query on a random row via Oracle

I am using ORACLE database and I am trying to access one random row from my SQL query however the query is not retrieving back a random row and I am not sure what I did wrong?
My query is:
SELECT a.car_id, b.product_id
FROM listing a, carProduct b
WHERE a.car_id = b.car_id
AND a.certified = 'TRUE'
AND b.product_id like '%CERT'
AND rownum = 1
ORDER BY DBMS_RANDOM.RANDOM
The rownum has to come after the order by. You need a subquery:
SELECT lcp.*
FROM (SELECT l.car_id, cp.product_id
FROM listing l join
carProduct cp
on l.car_id = cp.car_id
WHERE l.certified = 'TRUE' AND cp.product_id like '%CERT'
ORDER BY DBMS_RANDOM.RANDOM
) lcp
WHERE rownum = 1;
Notes:
Learn to use proper, explicit JOIN syntax. Simple rule: Never use commas in the FROM clause.
Use table aliases that make sense, such as abbreviations for the table names.
The rownum = 1 needs to go in the outer query.
In Oracle 12c+, you don't need a subquery. You can just use fetch first 1 row only.

SQL pagination using INNER JOINs and filtering with LIKE

This query feeds a data table with sorting, filtering, and pagination. All features worked fine until I added the INNER JOIN and then i got:
The multi-part 'identifier "Types.Description" could not be bound
if i remove the second WHERE clause at the end of the query the LIKE statements work, but i lose pagination. I removed some of the LIKE clauses to try and clean up this monstrous query.
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY TAG asc) AS RowNumber, *
FROM (
SELECT (SELECT COUNT(*) FROM Instruments) AS TotalDisplayRows, (SELECT COUNT(*) FROM Instruments) AS TotalRows, Instruments.Tag, Instruments.Location, Instruments.Description, Types.Description As TypeDesc, Manufacturer.Name, Lease.Name as LeaseName, Facility.Name as FacName
FROM Instruments
INNER JOIN Types ON Instruments.Type = Types.ID
INNER JOIN Manufacturer ON Instruments.Manufacturer = Manufacturer.ID
INNER JOIN Facility ON Instruments.Facility = Facility.ID
INNER JOIN Lease ON Instruments.Lease = Lease.ID
WHERE (Types.Description LIKE '%Cat%')
) RawResults
) Results
WHERE (Types.Description LIKE '%Cat%') AND RowNumber BETWEEN 1 AND 10
I think this is your problem
WHERE (types.description LIKE '%Cat%')
You can't do this because you are actually selecting from your derived table named Results and you aliased the column as TypeDesc.
So it should be
WHERE (results.typeDesc LIKE '%Cat%')

MYSQL top N rows from multiple table join

Like, there is top keyword in sql server 2005, how to select top 1 row in mysql if i have join on multiple table & want to retrieve extreme of each ID/column. Limit restricts the no. of row returns so it can't solve my problem.
SELECT v.*
FROM document d
OUTER APPLY
(
SELECT TOP 1 *
FROM version v
WHERE v.document = d.id
ORDER BY
v.revision DESC
) v
or
SELECT v.*
FROM document d
LEFT JOIN
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY v.id ORDER BY revision DESC)
FROM version
) v
ON v.document = d.id
AND v.rn = 1
The latter is more efficient if your documents usually have few revisions and you need to select all or almost all documents; the former is more efficient if the documents have many revisions or you need to select just a small subset of documents.
Update:
Sorry, didn't notice the question is about MySQL.
In MySQL, you do it this way:
SELECT *
FROM document d
LEFT JOIN
version v
ON v.id =
(
SELECT id
FROM version vi
WHERE vi.document = d.document
ORDER BY
vi.document DESC, vi.revision DESC, vi.id DESC
LIMIT 1
)
Create a composite index on version (document, revision, id) for this to work fast.
If I understand you correctly, top doesn't solve your problem either. top is exactly equivalent to limit. What you are looking for is aggregate functions, like max() or min() if you want the extremes. for example:
select link_id, max(column_a), min(column_b) from table_a a, table_b b
where a.link_id = b.link_id group by link_id