Finding MAX id from table with conditions - sql

There is a table with columns: id, name, age.
I need to find the max value of id and display name and id, where name starts with just A.
I used the query below to get the results, but this query doesn't return the unique row.
Its will retrieve from DB all rows where name start with, for example A, and all id's will be listed in the results set. My query HQL is:
SELECT t.name, MAX(t.id)
FROM table t
WHERE t.name LIKE 'A%' AND t.age= :age
GROUP BY t.name

The WHERE clause is filtering your data by the criteria you want, but it's SELECT and GROUPING by the name instead of just the first letter.
So what you need to do is 2 steps. First report the Max(ID) that satisfies your criteria. Next, you'll want to join that ID back to the data to retrieve the name.
So, this is your first into into the wonderful world of subqueries:
SELECT t1.*
FROM
table t1
INNER JOIN
(
SELECT MAX(id) AS max_id
FROM table
WHERE name LIKE 'A%' AND age= :age
) AS toprecord
ON t1.id = toprecord.max_id

I think you want this:
SELECT t.*
FROM table t
WHERE t.name LIKE 'A%' AND t.age= :age
ORDER BY t.id DESC
LIMIT 1;

Related

Use value of a field from a table dynamically in the 'where' clause of a HQL query?

Can one filter a table dynamically with a 'where' clause acting on a value of a field from another table under some other conditions such that it is made sure only one row is returned? Can I do something like this?
SELECT COUNT(*) FROM stud t1
WHERE t1.name==SELECT name FROM (
SELECT name, row_number() over (PARTITION BY name) AS rn
FROM stud t2) t3
WHERE t3.rn==1;
Of course, the above query is just a dummy one, but is filtering on where clause like above possible theoretically? If not how could one achieve such a functionality in the cases of more complex queries?
Yes. Query can be made like this:
SELECT COUNT(*) FROM stud t1
WHERE t1.name = (SELECT name
from sometable
where somecondition);
but you need to make sure that the subquery return zero or one row. If your query may return more than one row, you can use IN instead:
SELECT COUNT(*) FROM stud t1
WHERE t1.name IN (SELECT name
from sometable
where somecondition);

Get Records By Most Recent Date From two tables

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.

Get the first instance of a row using MS Access

EDITED:
I have this query wherein I want to SELECT the first instance of a record from the table petTable.
SELECT id,
pet_ID,
FIRST(petName),
First(Description)
FROM petTable
GROUP BY pet_ID;
The problem is I have huge number of records and this query is too slow. I discovered that GROUP BY slows down the query. Do you have any idea that could make this query faster? or better, a query wherein I don't need to use GROUP BY?
"The problem is I have huge number of records and this query is too slow. I discovered that GROUP BY slows down the query. Do you have any idea that could make this query faster?"
And an index on pet_ID, then create and test this query:
SELECT pet_ID, Min(id) AS MinOfid
FROM petTable
GROUP BY pet_ID;
Once you have that query working, you can join it back to the original table --- then it will select only the original rows which match based on id and you can retrieve the other fields you want from those matching rows.
SELECT pt.id, pt.pet_ID, pt.petName, pt.Description
FROM
petTable AS pt
INNER JOIN
(
SELECT pet_ID, Min(id) AS MinOfid
FROM petTable
GROUP BY pet_ID
) AS sub
ON pt.id = sub.MinOfid;
Your Query could change as,
SELECT ID, pet_ID, petName, Description
FROM petTable
WHERE ID IN
(SELECT Min(ID) As MinID FROM petTable GROUP BY pet_ID);
Or use the TOP clause,
SELECT petTable.petID, petTable.petName, petTable.[description]
FROM petTable
WHERE petTable.ID IN
(SELECT TOP 1 ID
FROM petTable AS tmpTbl
WHERE tmpTbl.petID = petTable.petID
ORDER BY tmpTbl.petID DESC)
ORDER BY petTable.petID, petTable.petName, petTable.[description];

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

How to get a count via a subselect

I'm trying to write an SQL which gets the number of rows in a table which has the same value as a specific column.
In this case, the table has a column called 'title'. For each row I return, along with the value of other columns for the row, I want to get the number of rows in the table which have the same value as that row's 'title' value.
For now, the best I have is:
select firstname, lastname, city, state, title, (select count from myTable where title = title);
Obviously, all this gives me is the number of rows in the table in my subselect.
How do I get the right side of the title = to refer to the value of the column's title?
Thanks for any help, anyone.
this is called "correlated subquery". It goes like this:
select firstname, lastname, title,
(select count(1) from table where title=a.title) title_count
from table a;
This is not tested, but I think that it should work for what you are trying to do
WITH titles AS (
SELECT
Title
, COUNT(*) AS Occurences
FROM myTable
GROUP BY Title
)
SELECT
t1.FirstName
, t1.LastName
, t1.City
, t1.state
, t1.title
, titles.Occurences
FROM myTable AS t1
INNER JOIN titles ON t1.Title = titles.Title
Most databases support the window/analytic functions. If you are using one of these (SQL Server, Oracle, Postgres, for example), you can do this as:
select t.firstname, t.lastname, t.title, t.city, t.state,
count(*) over (partition by title) as numwithtitle
from t