SQL selecting specific DISTINCT rows - sql

I'm trying to extract some data were the Event column is distinct but I specifically want only rows that contain the highest number from the Value column, I'm thinking it's some mis-mash of using DISTINCT and GROUP BY but my sql knowledge is limited at the moment, any help would be great

Try this out:
SELECT [EVENT]
,MAX([Value])
FROM [MyTable]
GROUP BY [EVENT]

The easiest way to do this is using either a subquery or row_number():
select event, value
from (select t.*, row_number() over (partition by event order by value desc) as seqnum
from mytable t
) t
where seqnum = 1;
or:
select t.*
from mytable t
where t.value = (select max(t2.value) from mytable t2 where t2.event = t.event);
You should be careful about naming columns. event and value might be reserved words in some databases.

How about SELECT [EVENT], MAX([Value]) FROM [My Table] GROUP BY [EVENT] ?

You were on the right track.
select event, max(value)
from test
group by event

Related

How to select only incremental records in BIG QUERY

I have a data in my database like as follows
and i am expecting the result like
Can anyone please help me how to write a select query for this. it is a kind of incremental load of data
Please help me on this
You can use window functions. You want the earliest version of each record, so:
select t.*
from (select t.*,
row_number() over (partition by empid, empname, sal order by create_time) as seqnum
from t
) t
where seqnum = 1;
If you want to detect changes, rather than the first occurrence of a set of values, you can use lag():
select t.*
from (select t.*,
lag(sal) over (partition by empid, empname order by create_time) as prev_sal
from t
) t
where prev_sal is null or prev_sal <> sal;
This handles salaries that decrease as well as increase.
SQL SERVER or ORACLE?
here I try for SQL SERVER
for all records, get the most recent previous record for the employee (if any) and check for changes since then, if none, do not select - therefore, only new or changed records are shown
SELECT t1.* FROM tab t1
OUTER APPLY
(SELECT TOP 1 t2.*
FROM tab t2
WHERE t1.empid = t2.empid
AND t2.create_time < t1.create_time
ORDER BY t2.create_time DESC
) IQ
WHERE IQ.empid IS NULL
OR IQ.ename != t1.ename
OR IQ.sal != t1.sal

SQL query to get maximum value for each day

So I have a table that looks something like this:
Now, I want the max totalcst for both days, something like this:
I tried using different variations of max and the Row_number funtion but still can't seem to get the result I want. My query:
select date,pid,max(quan*cst), totalcst
from dbo.test1
group by date, pid
But this returns all the records. So if somebody can point me towards the right direction, that would be very helpful.
Thanks in advance!
ROW_NUMBER should work just fine:
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY [date] ORDER BY totalcst)
FROM dbo.YourTable
)
SELECT [date],
pid,
totalcst
FROM CTE
WHERE RN = 1
;
Here is one simple way:
select t.*
from test1 t
where t.totalcst = (select max(t2.totalcst) from test1 t2 where t2.date = t.date);
This often has the best performance if you have an index on (date, totalcst). Of course, row_number()/rank() is also a very acceptable solution:
select t.*
from (select t.*, row_number() over (partition by date order by totalcst desc) as seqnum
from test1
) t
where seqnum = 1;

SQL Server Group By with Max on Date field

I hope i can explain the issue i'm having and hopefully so can point me in the same direction.
I'm trying to do a group by (Email Address) on a subset of data, then i'm using a max() on a date field but because of different values in other fields its bring back more rows then require.
I would just like to return the max record per email address and return the fields that are on the same row that are on the max record.
Not sure how i can write this query?
This is a task for ROW_NUMBER:
select *
from
(
select t.*,
-- assign sequential number starting with 1 for the maximum date
row_number() over (partiton by email_address order by datecol desc) as rn
from tab
) as dt
where rn = 1 -- only return the latest row
You can write this query using row_number():
select t.*
from (select t.*,
row_number() over (partition by emailaddress order by date desc) as seqnum
from t
) t
where seqnum = 1;
How about something like this?
select a.*
from baseTable as a
inner join
(select Email,
Max(EmailDate) as EmailDate
from baseTable
group by Email) as b
on a.Email = b.Email
and a.EmailDate = b.EmailDate

Show entire record from table with minimum timestamp in a group

I have been trying for about three hours to solve this problem but cannot find the solution.
How would I show the entire row (all 20 columns) for the first occurance (minimum time) of each name in my table?
For example, I would like to do something like this, which does not work:
SELECT name, MIN(time), col1, col2, col3, col4
FROM table
GROUP BY name;
You have to first get the minimum time for each name, and then join back to your original table where the name/time matches.
To get the minimum time:
SELECT name, MIN(time) AS minTime
FROM myTable
GROUP BY name;
Then, get all columns:
SELECT m.*
FROM myTable m
JOIN(
SELECT name, MIN(time) AS minTime
FROM myTable
GROUP BY name) tmp ON tmp.name = m.name AND tmp.minTime = m.time;
Most databases support ANSI standard window functions. With these, you can just do:
select t.*
from (select t.*, row_number() over (partition by name order by time) as seqnum
from table t
) t
where seqnum = 1;

Select the first instance of a record

I have a table, myTable that has two fields in it ID and patientID. The same patientID can be in the table more than once with a different ID. How can I make sure that I get only ONE instance of every patientID.?
EDIT: I know this isn't perfect design, but I need to get some info out of the database and today and then fix it later.
You could use a CTE with ROW_NUMBER function:
WITH CTE AS(
SELECT myTable.*
, RN = ROW_NUMBER()OVER(PARTITION BY patientID ORDER BY ID)
FROM myTable
)
SELECT * FROM CTE
WHERE RN = 1
It sounds like you're looking for DISTINCT:
SELECT DISTINCT patientID FROM myTable
you can get the same "effect" with GROUP BY:
SELECT patientID FROM myTable GROUP BY patientID
The simple way would be to add LIMIT 1 to the end of your query. This will ensure only a single row is returned in the result set.
WITH CTE AS
(
SELECT tableName.*,ROW_NUMBER() OVER(PARTITION BY patientID ORDER BY patientID) As 'Position' FROM tableName
)
SELECT * FROM CTE
WHERE
Position = 1