Taking different values for each different id - sql

I want to use only the highest value from a column when there's multiples for each id, but also the lowest from another column when theres multiples:
Like in this case we have 2 lines with the same id 11024, I want the result to only show a single line for each id, but the dtStart must be the lowest and the dtEnd must be the higher:
(this image was fabricated, just to show how it should be)
My select is:
SELECT top 100
id ,
min (dtStart ) dtStart,
max (dtEnd ) dtEnd
FROM T_registable
WHERE sup_id = 3356
GROUP by
id, dtStart, dtEnd
I tried to use "min"/"max" value, tried union all, tried to use partition by.

Removing dtStart and dtEnd from your GROUP BY clause should solve the issue. TOP is usually used with an ORDER BY.
SELECT
id,
MIN(dtStart) AS dtStart,
MAX(dtEnd) AS dtEnd
FROM T_registable
WHERE sup_id = 3356
GROUP BY id

Related

Getting MAX of a column and adding one more

I'm trying to make an SQL query that returns the greatest number from a column and its respective id.
For more information I have two columns ID and NUMBER. Both of them have 2 entries and I want to get the highest number with the ID next to it. This is what I tried but didn't success.
SELECT ID, MAX(NUMBER) AS MAXNUMB
FROM TABLE1
GROUP BY ID, MAXNUMB;
The problem I'm experiencing is that it just shows ALL the entries and if I add a "where" expression it just shows the same (all entries [ids+numbers]).
Pd.: Yes, I got what I wanted but only with one column (number) if I add another column (ID) to select it "brokes".
Try:
SELECT
ID,
A_NUMBER
FROM TABLE1
WHERE A_NUMBER = (
SELECT MAX(A_NUMBER)
FROM TABLE1);
Presuming you want the IDs* of the row with the highest number (and not, instead, the highest number for each ID -- if IDs were not unique in your table, for example).
* there may be more than one ID returned if there are two or more IDs with equal maximum numbers
you can try this
Select ID,maxNumber
From
(
SELECT
ID,
(Select Max(NUMBER) from Tmp where Id = t.Id) maxNumber
FROM
Tmp t
)T1
Group By ID,maxNumber
The query you posted has an illegal column name (number) and is group by the alias for the max value, which is illegal and also doesn't make sense; and you can't include the unaliased max() within the group-by either. So it's likely you're actually doing something like:
select id, max(numb) as maxnumb
from table1
group by id;
which will give one row per ID, with the maximum numb (which is the new name I've made up for your numeric column) for each ID. Or as you said you get "ALL the entries" you might have group by id, numb, which would show all rows from the table (unless there are duplicate combinations).
To get the maximum numb and the corresponding id you could group by id only, order by descending maxnumb, and then return the first row only:
select id, max(numb) as maxnumb
from table1
group by id
order by maxnumb desc
fetch first 1 row only
If there are two ID with the same maxnumb then you would only get one of them - and which one is indeterminate unless you modify the order by - but in that case you might prefer to use first 1 row with ties to see them all.
You could achieve the same thing with a subquery and analytic function to generating a ranking, and have the outer query return the highest-ranking row(s):
select id, numb as maxnumb
from (
select id, numb, dense_rank() over (order by numb desc) as rnk
from table1
)
where rnk = 1
You could also use keep to get the same result as first 1 row only:
select max(id) keep (dense_rank last order by numb) as id, max(numb) as maxnumb
from table1
fiddle

SQL: select next available date for multiple records

I have an oracle DB.
My table has ID and DATE columns (and more).
I would like to select for every ID the next available record after a certain date. For only one ID the query would be:
SELECT * FROM my_table
WHERE id = 1 AND date >= '01.01.2018'
(just ignoring the to_date() function)
How would that look like for multiple IDs? And I do want to SELECT *.
Thanks!
We can use ROW_NUMBER here:
SELECT ID, date -- and maybe other columns
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY date) rn
FROM my_table
WHERE date >= date '2018-01-01'
) t
WHERE rn = 1
The idea here is to assign a row number to each ID partition, starting with the earliest date which occurs after the cutoff you specify. The first record from each partition would then be the immediate next date, assuming it exists.

How to select row with group into 2 specific values by Descending order?

I would like to select queries a table with group by only 2 value in specific field. Like example bellow.
I have a table that normally having 2 value each minute. But some time having more than 2 value in each minute and I have selected by descending order.
Avoid that, I want to field of minute value [TimeStamp] can be group by 2 item based descending order and skip when have more than 2 value.
SELECT TOP 10
dbo.ConRadVacuum.[TimeStamp],
dbo.ConRadVacuum.Tag,
dbo.ConRadVacuum.[Value]
FROM
ConRadVacuum
ORDER BY
[TimeStamp] DESC
I want "selected row" (32 minute) can be selected only two like the other rows
I think you can use row_number() function by partitioning over minute part of your timestamp field, something like this:
select *
from (
select *,
row_number() over (
partition by datepart(minute, cast([TimeStamp] as datetime))
--^^ I use `datepart()` over cast of your timestamp field
--If your field is `datetime` you don't need to `cast`
order by [TimeStamp] desc) seq
from t) tt
where seq <= 2;
SQL Fiddle Demo
I didn't get your question very well, but i think you can put your query in CTE and add ROW_Number to it, then select your cte where your row number field is 1 or 2

Need a SQL query to get a single, max date when the max date is not unique

My apologies if this has been asked and wasn't able to find this. I've searched for a long time, with no luck.
My table is named RESULT -
DATE TEST_NUM RESULT_NUM
11/16/2010 09:27:11 AM 123456 123111
11/16/2010 09:27:11 AM 123456 123222
11/16/2010 09:27:11 AM 123456 123333
For a given TEST_NUM, I only want to return the max date just one time, and it doesn't matter what the other column entries are -
11/16/2010 09:27:11 AM 123456 123111
SELECT RESULT.DATE,
RESULT.RESULT_NUM,
RESULT.TEST_NUM
FROM RESULT
WHERE RESULT.TEST_NUM = 123456
AND RESULT.DATE = (SELECT MAX(R1.DATE)
FROM RESULT R1
WHERE r1.TEST_NUM = RESULT.TEST_NUM)
But as you guessed, I don't get 1 result - I get all three. I've tried everything! Please help this newbie!
To get the maximum date:
SELECT MAX(RESULT.DATE) FROM RESULT
To get an entire row for any one of the rows that hold the maximum date:
SELECT * FROM
(
SELECT *
FROM RESULT
WHERE RESULT.TEST_NUM = 123456
ORDER BY RESULT.DATE DESC
)
WHERE rownum = 1
UPDATE : -
select max(DATE) from RESULT where RESULT.TEST_NUM = 123456 group by RESULT.TEST_NUM
Here is an example -
select id,max (date_column) from your_table group by id
where id is the column you want the values for max date for, this will give you max date for each of the unique entries for id in that table out of the many date entries, since what I understood was that you have multiple dates and want the max.
Why won't this work
SELECT MAX(DATE) FROM TABLE
SELECT date_column FROM table GROUP BY date_column HAVING COUNT(*)>1 ORDER BY date_column DESC LIMIT 1
This will return the highest date_column ( ORDER BY date_column DESC ) that is not unique ( HAVING COUNT(*) > 1 )
select distinct max(date_column)
into variable
from table
where condition;
Adding the distinct will ensure that if the data is the same then it will only return one record.

Oracle query needs to return the highest date from result

I have a really big query in which makes some troubles for me because one join can return several rows. I only want the latest row (identified by a date field) in this result set, but I cant seem to put together the correct query to make it work.
The query I need MAX date from is:
SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043;
Teh custid is really found through a join, but for simplicity I've added it to the where clause here. This query produces the following result:
custid grunn date
167043 "Test 1" 19.10.2005 12:33:18
167043 "Test 2" 28.11.2005 16:23:35
167043 "Test 3" 14.06.2010 15:43:16
How can I retrieve only one record from this resultset? And that record is the one with the highest date? Ultimately Im putting this into a big query which does alot of joins, so hopefully I can use this example into my bigger query.
You can do this:
SELECT * FROM
( SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043
ORDER BY date DESC
)
WHERE ROWNUM = 1;
You can solve it by using analytic functions. Try something like this:
select custid
,reason
,date
from (select custid
,reason
,date
,row_number() over(partition by cust_id order by date desc) as rn
from opt)
where rn = 1;
This is how it works: The resultset is divided into groups of cust_id (partition by). In each group, the rows will be sorted by the date column in descending order (order by). Each row within the group will be assigned a sequence number (row_number) from 1 to N.
This way the row with the highest value for date will be assigned 1, the second latest 2, third latest 3 etc..
Finally, I just pick the rows with nr = 1, which basically filters out the other rows.
Or another way using the LAST function in its aggregate form.
with my_source_data as (
select 167043 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual union all
select 167043 as custid, 'Test 2' as reason, date '2010-10-02' as the_date from dual union all
select 167043 as custid, 'Test 3' as reason, date '2010-10-03' as the_date from dual union all
select 167044 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual
)
select
custid,
max(reason) keep (dense_rank last order by the_date) as reason,
max(the_date)
from my_source_data
group by custid
I find this quite useful as it rolls the process of finding the last row and the value all into one. The use of MAX (or another aggregate function such as MIN) in case that the combination of the grouping and the order by is not deterministic.
This function will basically take the contents of the column based on the grouping, order it by the ordering given then take the last value.
rather than using row_number() I think it's better to select what you actually want to select (e.g. the last date)
SELECT custid
, reason
, date
from
(
SELECT custid
, reason
, date
, max(opt.date) over (partition by opt.custid order by opt.date) last_date
FROM OPT opt
WHERE opt.custid = 167043;
)
where date = last_date
both solutions with ROW_NUMBER and KEEP are good. I would tend to prefer ROW_NUMBER when retrieving a large number of columns, and keep KEEP for one or two columns, otherwise you will have to deal with duplicates and the statement will get pretty unreadable.
For a small number of columns however, KEEP should perform better