SQL query for last user action - sql

I am trying to get an SQL statement to work which will show a list of users in the database and their last action.
The current table format is;
tblUser:
id, username, password
tblAction:
id, uid, action, date
The SQL statment I have at present is;
SELECT *
FROM tblUser
FULL OUTER JOIN Location
ON tblUser.id=tblAction.uid
WHERE action IS NOT NULL
ORDER BY date DESC
I have used limit 1 but this hasn't worked.
I have also tried;
SELECT *
FROM tblAction T1
WHERE date = (
SELECT max(date)
FROM tblUser T2
WHERE T2.uid=T1.id
Please could someone help me?
This is an SQL command to be executed in an admin panel in PHP and is not MySQL.

Use ROW_NUMBER:
;WITH CTE AS
(
SELECT U.*,
A.[action],
A.[date],
RN = ROW_NUMBER() OVER(PARTITION BY U.id ORDER BY A.[date] DESC)
FROM tblUser U
LEFT JOIN tblAction A
ON U.id = A.uid
)
SELECT *
FROM CTE
WHERE RN = 1;

try use RANK()/DENSE_RANK()/ROW_NUMBER()
FIDDLE DEMO
RANK:
;WITH CTE AS
(
SELECT a.*,
b.action,
b.date,
Rk = RANK() OVER(PARTITION BY a.id ORDER BY b.[date] DESC)
FROM tblUser a
LEFT JOIN tblAction b
ON a.id = b.uid
)
SELECT *
FROM CTE
WHERE Rk = 1;

Related

How to implement a LEFT OUTER JOIN CLAUSE after WITH AS?

Currently trying to figure out how to implement a SQL LEFT OUTER JOIN while using the SQL WITH AS clause. My code breaks down into 3 SELECT statements while using the same table, then using LEFT OUTER JOIN to merge another table on the id.
I need 3 SELECT statements before joining because I need a SELECT statement to grab the needed columns, ROW RANK the time, and set WHERE clause for the ROW RANK.
SELECT *
(
WITH employee AS
(
SELECT id, name, department, code, time, reporttime, scheduled_time
FROM table1 AS a
WHERE department = "END"
),
employe_v2 as
(
SELECT address
,ROW_NUMBER() OVER (PARTITION BY id ORDER BY time desc, reporttime desc, scheduled_time desc) AS row_rank
FROM table1 AS b
)
SELECT *
FROM employee, employee_v2
WHERE row_rank = 1
) t1
LEFT OUTER JOIN
(
SELECT b.id, b.new_code, b.date
FROM table2 AS b
WHERE b.newcode != "A"
) t2
ON t1.id = t2.id
Group BY t1.id, t1.name, t1.department, t1.code, t1.time, t1.reporttime,
t1.scheduled_time, t1.row_rank, t2.id, t2.new_code, t2.date
How I could fix my code?
not sure if group by is needed, i see no aggregation whatsover
but if it's something you need , you can add at the end of final select and ofcourse you have to take care of columns/aggregation in select
nevertheless you can simplify your query as below :
with employee as (
select * from (
select id, name, department, code, time, reporttime, scheduled_time, address
,row_number() over (partition by id order by time desc, reporttime desc, scheduled_time desc) AS row_rank
from table1
) t where row_rank =1
)
select t1.*, b.id, b.new_code, b.date
from employee t1
left join table2 as t2
on t1.id = t2.id
where t2.newcode != "A"

Removing duplicate values from a column in SQL

I have two tables A (group_id, id, subject) and B (id, date). Below is the joint table of tables A and B on id. I have tried using distinct and partition to remove the duplicates in group_id(field) only, but no luck:
My code:
select
a.group_id, a.id, a.subject, b.date
from
A a
inner join
(select
b.*,
row_number() over (partition by group_id order by date asc) as seqnum
from
B b) b on a.id = b.id and seqnum = 1
order by
date desc;
I got this error when I ran the code:
Partitioning can not be used stand-alone in query near 'partition by group_id order by date asc) as seqnum from B' at line 1
This is my expected result:
Thank you in advance!
It looks like you want the earliest date for each row in the table you show. Your question mentions two tables, but you only show one.
I recommend a correlated subquery in most databases:
select b.*
from b
where b.date = (select min(b2.date)
from b b2
where b2.group_id = b.group_id
);
I see. You need to join first and then use row_number():
select ab.*
from (select a.group_id, a.id, a.subject, b.date,
row_number() over (partition by a.group_id order by b.date) as seqnum
from A a join
B b
on a.id = b.id
) ab
where seqnum = 1
order by date desc;
You are almost there. But the column that you try to use to partition (ie group_id) comes from table a, which is not available in the subquery.
You would need to JOIN and assign the row number in a subquery, and then filter in the outer query.
select *
from (
select
a.group_id,
a.id,
a.subject,
b.date,
row_number() over (partition by a.group_id order by b.date asc) as seqnum
from a
inner join b on ON a.id = b.id
)
where seqnum = 1
ORDER BY date desc;
Another way to achieve your goal though it may not be the efficient one
SELECT
A.group_id, A.id, B.Date, A.subject
FROM A
INNER JOIN B
ON A.Id = B.Id
INNER JOIN
(
SELECT
A.Group_id, MIN(B.Date) AS Date
FROM A
INNER JOIN B
ON A.Id = B.Id
GROUP BY A.group_id
) AS supportTable
ON A.group_id = supportTable.group_id
AND B.Date = supportTable.Date

Select group with maximum value of aggregate function

I have this query
select dca_sif, maxupp
from (select d.sifra dca_sif , sum(col1) as maxup
from tableD d join tablev v on d.id=v.d_id
join tableT t on v.id=t.v_id
group by d.sif
order by maxup desc
)
where rownum=1;
This returns first value, but If I have more groups with same maxup, how can I return all of them?
If I delete rownum=1, it returns all groups and coresponding maxup.
I want to return max(sum(col1)) but this cause error. Database is oracle.
You can try somthing like this:-
SELECT dca_sif, MAX(maxup)
FROM (SELECT d.sifra dca_sif , SUM(col1) AS maxup
FROM tableD d JOIN tablev v ON d.id=v.d_id
JOIN tableT t ON v.id=t.v_id
GROUP BY d.sif
ORDER BY maxup DESC
)
WHERE ROWNUM=1
GROUP BY dca_sif;
This might be helpful to you.
You can combine your select with the same select, but without the rownum limitation. Than join on the max id. There are many tables in your statement, so it is difficult to test for me, but this should work:
SELECT count(qry2.dcasif) || ' groups', sum( qry2.maxup2)
FROM ( SELECT dca_sif, MAX (maxup) AS maxup1
FROM ( SELECT d.sifra dca_sif, SUM (col1) AS maxup
FROM tabled d
JOIN tablev v ON d.id = v.d_id
JOIN tablet t ON v.id = t.v_id
GROUP BY d.sif
ORDER BY maxup DESC)
WHERE ROWNUM = 1
GROUP BY dca_sif) qry1
, ( SELECT dca_sif, MAX (maxup) AS maxup2
FROM ( SELECT d.sifra dca_sif, SUM (col1) AS maxup
FROM tabled d
JOIN tablev v ON d.id = v.d_id
JOIN tablet t ON v.id = t.v_id
GROUP BY d.sif
ORDER BY maxup DESC)
GROUP BY dca_sif) qry2
WHERE qry1.maxup1 = qry2.maxup2
SELECT dca_sif, maxup
FROM
(SELECT a.*,rank() over(order by maxup desc)as Rank
FROM (SELECT d.sifra dca_sif , SUM(col1) AS maxup
FROM tableD d JOIN tablev v ON d.id=v.d_id
JOIN tableT t ON v.id=t.v_id
GROUP BY d.sif
)a)
WHERE Rank=1

How to Select master table data and select referance table top one data sql query

i need an sql query which should return the master table entry and its child table entry (the latest one entry only). I used inner join for this. But i its not working fine.
Can anyone give a give me a proper query for this
Thanks in advance
In SQLServer2005+ use option with OUTER APPLY operator
SELECT *
FROM master t1 OUTER APPLY (
SELECT TOP 1 t2.Col1, t2.Col2 ...
FROM child t2
WHERE t1.Id = t2.Id
ORDER BY t2.CreatedDate DESC
) o
OR option with CTE and ROW_NUMBER() ranking function
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY t1.Id ORDER BY t2.CreatedDate DESC) AS rn
FROM master t1 JOIN child t2 ON t1.Id = t2.Id
)
SELECT *
FROM cte
WHERE rn = 1
Try this,
SELECT ID, DATE
(
SELECT M.ID, C.DATE, ROW_NUMBER() OVER(PARTITION BY M.ID ORDER BY C.DATE DESC) RN
FROM MASTER M
JOIN CHILD C
ON C.ID = M.ID
) A
WHERE RN = 1

Add row number to this T-SQL query

How can I add ROW numbers to this query result?
SELECT DISTINCT
VehicleSpecs.SubmittedById,
COUNT(VehicleSpecs.SubmittedById) AS NumCars,
aspnet_Users.UserName
FROM
VehicleSpecs
INNER JOIN aspnet_Users ON VehicleSpecs.SubmittedById = aspnet_Users.UserId
WHERE
(LEN(VehicleSpecs.SubmittedById) > 0)
GROUP BY
VehicleSpecs.SubmittedById,
aspnet_Users.UserName
ORDER BY
NumCars DESC
Add: ROW_NUMBER() OVER (ORDER BY NumCars)
EDIT:
WITH t1 AS
( SELECT DISTINCT
VehicleSpecs.SubmittedById ,
COUNT(VehicleSpecs.SubmittedById) AS NumCars ,
aspnet_Users.UserName
FROM VehicleSpecs
INNER JOIN aspnet_Users ON VehicleSpecs.SubmittedById = aspnet_Users.UserId
WHERE ( LEN(VehicleSpecs.SubmittedById) > 0 )
GROUP BY VehicleSpecs.SubmittedById ,
aspnet_Users.UserName
)
SELECT ROW_NUMBER() OVER ( ORDER BY NumCars ), *
FROM t1
ORDER BY NumCars
Wrap you entire query in a sub query and add row_number in the outer query.
select *, row_number() over(order by (select 0)) as rn
from
(
select distinct -- your columns
from YourTable
) as T
order by NumCars desc