Why MAX always returns a row?
What you are seeing is called aggregation. MAX
is an aggregation function, as are MIN
, SUM
, COUNT
, AVG
, etc. Aggregation functions lead to exactly one result row, unless you specify a GROUP BY
clause or a HAVING
clause.
A GROUP BY
results in one or more rows, as it says "Give me an aggegation result per ___", e.g. "Give me the number of employees and the highest salary per department" which would result in one row per department.
The HAVING
clause is like a WHERE
clause on the aggragation result. In the given example you could add "but only for departments with at least ten employees" for instance.
Hence, if you don't want a result row in case there is no value in col (i.e. there exists no maximum value), add a HAVING
clause:
SELECT MAX(col) FROM my_table HAVING MAX(col) IS NOT NULL;
Here is the SQL Server documentation on aggregation functions: https://docs.microsoft.com/de-de/sql/t-sql/functions/aggregate-functions-transact-sql?view=sql-server-ver15
EDIT:
As to whether there exist means to return nulls instead of no row in case of no data matching the WHERE
clause: The WHERE
clause eliminates the rows from the result, so we must find ways to get around this. One is outer joins, another is unioned queries and there may be other methods, too.
An example:
select dept_id, dept_name from departments where boss = 'Mr. X';
would return no row, if there isn't any department where the boss is Mr. X.
But we get null rows when outer joining tables:
select d.dept_id, d.dept_name
from (select 1) dummy
left outer join departments d on boss = 'Mr. X';
Or we combine two queries, one for the match and one for no match:
select dept_id, dept_name from departments where boss = 'Mr. X'
union all
select null, null where not exists (select * from departments where boss = 'Mr. X');
How to select single row based on the max value in multiple rows
The way I try to solve SQL problems is to take things step by step.
- You want the maximum revision for the maximum minor version corresponding to the maximum major version for each product.
The maximum major number for each product is given by:
SELECT Name, MAX(major) AS Major FROM CA GROUP BY Name;
The maximum minor number corresponding to the maximum major number for each product is therefore given by:
SELECT CA.Name, CA.Major, MAX(CA.Minor) AS Minor
FROM CA
JOIN (SELECT Name, MAX(Major) AS Major
FROM CA
GROUP BY Name
) AS CB
ON CA.Name = CB.Name AND CA.Major = CB.Major
GROUP BY CA.Name, CA.Major;
And the maximum revision (for the maximum minor version number corresponding to the maximum major number for each product), therefore, is given by:
SELECT CA.Name, CA.Major, CA.Minor, MAX(CA.Revision) AS Revision
FROM CA
JOIN (SELECT CA.Name, CA.Major, MAX(CA.Minor) AS Minor
FROM CA
JOIN (SELECT Name, MAX(Major) AS Major
FROM CA
GROUP BY Name
) AS CB
ON CA.Name = CB.Name AND CA.Major = CB.Major
GROUP BY CA.Name, CA.Major
) AS CC
ON CA.Name = CC.Name AND CA.Major = CC.Major AND CA.Minor = CC.Minor
GROUP BY CA.Name, CA.Major, CA.Minor;
Tested - it works and produces the same answer as Andomar's query does.
Performance
I created a bigger volume of data (11616 rows of data), and ran a benchmark timing of Andomar's query against mine - target DBMS was IBM Informix Dynamic Server (IDS) version 11.70.FC2 running on MacOS X 10.7.2. I used the first of Andomar's two queries since IDS does not support the comparison notation in the second one. I loaded the data, updated statistics, and ran the queries both with mine followed by Andomar's and with Andomar's followed by mine. I also recorded the basic costs reported by the IDS optimizer. The result data from both queries were the same (so the queries are both accurate - or equally inaccurate).
Table unindexed:
Andomar's query Jonathan's query
Time: 22.074129 Time: 0.085803
Estimated Cost: 2468070 Estimated Cost: 22673
Estimated # of Rows Returned: 5808 Estimated # of Rows Returned: 132
Temporary Files Required For: Order By Temporary Files Required For: Group By
Table with unique index on (name, major, minor, revision):
Andomar's query Jonathan's query
Time: 0.768309 Time: 0.060380
Estimated Cost: 31754 Estimated Cost: 2329
Estimated # of Rows Returned: 5808 Estimated # of Rows Returned: 139
Temporary Files Required For: Group By
As you can seen, the index dramatically improves the performance of Andomar's query, but it still seems to be more expensive on this system than my query. The index gives a 25% time saving for my query. I'd be curious to see comparable figures for the two versions of Andomar's query on comparable volumes of data, with and without the index. (My test data can be supplied if you need it; there were 132 products - the 3 listed in the question and 129 new ones; each new product had (the same) 90 version entries.)
The reason for the discrepancy is that the sub-query in Andomar's query is a correlated sub-query, which is a relatively expensive process (dramatically so when the index is missing).
Return the row includes the maximum value of specific column if two rows have the same values.
The question, sample data, and desired results are lacking a bit.
But if I understand your question, you can use the WITH TIES
clause in concert with Row_Number()
Example
Select Top 1 with ties *
From YourTable
Order By Row_Number() over (Partition By YourCol1 Order By YourLastCol Desc)
Edit Use Dense_Rank() if you want to see ties
SQL select multiple max rows where ID is same
Query:
SQLFIDDLEExample
SELECT t1.*
FROM Table1 t1
WHERE t1.Date = (SELECT MAX(t2.Date)
FROM Table1 t2
WHERE t2.AccountID = t1.AccountID)
Result:
| ROW | DATE | ACCOUNTID |
--------------------------------------------------------
| 1 | February, 21 2013 00:30:00+0000 | A0M8FA1003YP |
| 2 | February, 21 2013 00:30:00+0000 | A0M8FA1003YP |
| 3 | February, 21 2013 00:30:00+0000 | A0M8FA1003YP |
| 7 | February, 12 2009 12:00:00+0000 | A023123332YP |
Return more than one row when using MAX SQL
this does not uses dense_rank(), should works on MySQL also
SELECT t.*
FROM yourtable t
INNER JOIN
(
SELECT PositionId, max(VoteCount) as VoteCount
FROM yourtable
GROUP BY PositionId
) m ON t.PositionId = m.PositionId
AND t.VoteCount = m.VoteCount
How to use MAX() for multiple occurrences of Max values in SQL
MAX()
is a scalar function returns a single value and not records so if you have multiple records that have the same value which is maximum, the following will still return only one value:
SELECT MAX(Value) FROM MyTable
If you want to get all records that have the maximum value, you can use
SELECT * FROM MyTable
WHERE Value = (SELECT MAX(Value) FROM MyTable)
SQL MAX join query returns multiple rows
Rows in a relational database have no order. There's no "last" entry unless something specifies an order.
In this case it appears the order is by ascending inventory_id_inventory
for each inventory_id_inventory
. Given that order, one can use the ROW_NUMBER()
ranking function to calculate a rank for each result of the join , eg :
SELECT
isni.id,
isni.inventory_id_inventory,
isni.issue_note_id_issue_notes,
isn.direction,
ROW_NUMBER() OVER(partition by inventory_id_inventory
order by issue_note_id_issue_notes desc) as rn
FROM issue_note_items isni
JOIN issue_notes isn ON isni.issue_note_id_issue_notes = isn.issue_note_id
partition by inventory_id_inventory
means we want a separate ranking per partition by inventory_id_inventory. order by issue_note_id_issue_notes desc
will return 1 for the largest ID, making it easier to filter for the "latest" entry.
It's not possible to refer to the rn
function in the where
clause. This can be fixed by using a CTE :
with notes as (
SELECT
isni.id,
isni.inventory_id_inventory,
isni.issue_note_id_issue_notes,
isn.direction,
ROW_NUMBER() OVER( partition by inventory_id_inventory
order by issue_note_id_issue_notes desc) as rn
FROM issue_note_items isni
JOIN issue_notes isn ON isni.issue_note_id_issue_notes = isn.issue_note_id
)
select *
from notes
where rn=1
order by issue_note_id_issue_notes
Using the following data :
create table issue_notes (issue_note_id int,direction int);
create table issue_note_items (id int, inventory_id_inventory int,issue_note_id_issue_notes int);
insert into issue_notes
values
(1,1),
(2,2),
(3,2),
(4,1),
(5,2),
(6,1);
insert into issue_note_items
values
(1,12 ,1),
(2,123,1),
(3,12 ,2),
(4,12 ,4),
(5,35 ,4),
(6,123,5),
(7,35 ,6);
The result will be :
|id |inventory_id_inventory |issue_note_id_issue_notes |direction |rn
|4 |12 |4 |1 |1
|6 |123 |5 |2 |1
|7 |35 |6 |1 |1
SQL Fiddle here
Check multiple rows for value, return only row with MAX/MIN
Well if you only want the newest row you could use the following:
SELECT TOP 1 key, name, value, date
FROM myTable
ORDER BY date desc
This should return the one row with the newest date in that table.
If you wanted the newest date for each name you could use group by:
SELECT name, max(date)
FROM myTable
WHERE key in(1,2,3,4)
GROUP BY name
Max is an aggregate function. Anytime you use an aggregate function any columns that are not being aggregated have to be specified in the group by clause.
So based on your expected results you probably want this:
;with namesWithMaxDate as(
select
name
,max(date) as date
from
myTable
group by
name
)
select
myTable.[key]
,myTable.name
,myTable.value
,myTable.date
from myTable
inner join
namesWithMaxDate
on
myTable.name = namesWithMaxDate.name and
myTable.date = namesWithMaxDate.date
This is slightly more complex because you have columns that you want returned that are not included in the grouping. Hence two statements to arrive at the final result set.
Final option: good old fashioned sub-query.
select
myTable.[key]
,myTable.name
,myTable.value
,myTable.date
from myTable
inner join
( select
name
,max(date) as date
from
myTable
group by
name ) as namesWithMaxDate
on
myTable.name = namesWithMaxDate.name and
myTable.date = namesWithMaxDate.date
More here about aggregate functions.
More here about group by.
Related Topics
How to Combine Two Completely Different SQL Queries into One Result
How to Select All the Columns of a Table Except One Column
How to Convert Milliseconds to Time(Hh:Mm:Ss) in Oracle
How to Include Results of SQL Count If Count=0
Remove Decimal Values Using SQL Query
Getting Two Counts and Then Dividing Them
How to Check If More Than One Column Is Not Null Per Record
How to Calculate Percentage of Counts in SQL
Auto Increment the Column Value by 1 Conditionally in Select Query in SQL
Sql Select Count for Multiple Columns in a Single Query
Splitting Date into 2 Columns (Date + Time) in SQL
A SQL Query to Get All the Records Where 5 Columns Are Same But Only One Column Is Different
Get the Number of Digits After the Decimal Point of a Float (With or Without Decimal Part)
How to Remove Line Feed Characters When Selecting Data from SQL Server
Node.Js Mssql Tedius Connectionerror: Failed to Connect to Localhost:1433 - Connect Econnrefused