SQL MAX Date Does Not Decipher Seconds - sql-server

I have a table which contains the following data:
ID | ObjectID | ActionDate
=======================================
12345 | 422107 | 2016-10-05 11:24:23.790
12346 | 422107 | 2016-10-05 11:24:28.797
I want to return the ID and max date, but the MAX function does not seem to be calculating down to seconds value (SS). Am I missing something, or is this a limitation with the MAX function? Here is the code I am using:
SELECT
TMOA.ObjectID AS [ObjID]
, TMOA.ID AS [ObjActionID]
, MAX(TMOA.ActionDate) AS [PrepDate]
FROM
TM_Procedure AS TMPRD
left join TM_ObjectAction AS TMOA ON TMPRD.ID = TMOA.ObjectID
GROUP BY
TMOA.ObjectID
, TMPRD.ID
, TMOA.ID

Looks like you're grouping by the ID of the table which is UNIQUE. More than likely that's why you're getting a record that you don't want. Just select the MAX(ActionDate) and see what you get.
If you get the records you want, then you have to figure out which column you are selecting/grouping by that is causing the records you don't want. My guess is that it's either TMOA.ObjectID or TMOA.ID

One option is to use the window function Row_Number()
Select *
From (
Select *
,RowNr=Row_Number() over (Partition By ObjectID Order by ActionDate Desc
From YourTable
) A
Where RowNr=1

Related

SQL GROUP BY with columns which contain mirrored values

Sorry for the bad title. I couldn't think of a better way to describe my issue.
I have the following table:
Category | A | B
A | 1 | 2
A | 2 | 1
B | 3 | 4
B | 4 | 3
I would like to group the data by Category, return only 1 line per category, but provide both values of columns A and B.
So the result should look like this:
category | resultA | resultB
A | 1 | 2
B | 4 | 3
How can this be achieved?
I tried this statement:
SELECT category, a, b
FROM table
GROUP BY category
but obviously, I get the following errors:
Column 'a' is invalid in the select list because it is not contained
in either an aggregate function or the GROUP BY clause.
Column 'b' is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
How can I achieve the desired result?
Try this:
SELECT category, MIN(a) AS resultA, MAX(a) AS resultB
FROM table
GROUP BY category
If the values are mirrored then you can get both values using MIN, MAX applied on a single column like a.
Seams you don't really want to aggregate per category, but rather remove duplicate rows from your result (or rather rows that you consider duplicates).
You consider a pair (x,y) equal to the pair (y,x). To find duplicates, you can put the lower value in the first place and the greater in the second and then apply DISTINCT on the rows:
select distinct
category,
case when a < b then a else b end as attr1,
case when a < b then b else a end as attr2
from mytable;
Considering you want a random record from duplicates for each category.
Here is one trick using table valued constructor and Row_Number window function
;with cte as
(
SELECT *,
(SELECT Min(min_val) FROM (VALUES (a),(b))tc(min_val)) min_val,
(SELECT Max(max_val) FROM (VALUES (a),(b))tc(max_val)) max_val
FROM (VALUES ('A',1,2),
('A',2,1),
('B',3,4),
('B',4,3)) tc(Category, A, B)
)
select Category,A,B from
(
Select Row_Number()Over(Partition by category,max_val,max_val order by (select NULL)) as Rn,*
From cte
) A
Where Rn = 1

Get unique values query with latest entries

I am trying to write a query to get unique transaction values, with the sale value and the latest date that took place.
Here is my query:
select transaction, sales, max(sale_date) from xyz_table where report_date = 20160718 group by transaction, sales;
This is the result that i get:
This is the sample data:
|transaction | sales| sale_date| report_date|
|1397115220084030| 0.000144| 20160714|20160718|
|13971230534538500| 0 | 20160716|20160718|
|13973937437448300| 0.000001| 20160716|20160718|
|13976744119997000| 0.008563| 20160714|20160718|
|13976744119997000| 0.002392| 20160715|20160718|
What i wanted was unique transactions with the latest sale date:
This is the required data:
|transaction | sales| sale_date| report_date|
|1397115220084030| 0.000144| 20160714|20160718|
|13971230534538500| 0 | 20160716|20160718|
|13973937437448300| 0.000001| 20160716|20160718|
|13976744119997000| 0.002392| 20160715|20160718|
I have tried to do max of sales but that still does not give the correct result:
select transaction, Max(sales), max(sale_date) from xyz_table where report_date = 20160718 group by transaction;
Wrong result:
This is the required data:
|transaction | sales| sale_date| report_date|
|1397115220084030| 0.000144| 20160714|20160718|
|13971230534538500| 0 | 20160716|20160718|
|13973937437448300| 0.000001| 20160716|20160718|
|13976744119997000| 0.008563| 20160715|20160718|
Please can someone help me.
Thanks
In Hive, you would use window functions:
select t.*
from (select t.*,
row_number() over (partition by transaction order by sale_date desc) as seqnum
from transactions t
) t
where seqnum = 1;
The MySQL query would be quite different, because it does not support this ANSI standard functionality.

Laravel - query builder to select multiple rows with unique column value (which has max value from another column)

I have a table like this
data | usage_date | usage_hour
x | 03/03/2016 | 05:30:30
y | 03/02/2016 | 11:30:30
z | 03/03/2016 | 07:30:30
p | 03/02/2016 | 05:30:30
When I run Laravel query I would like see following rows being selected
y | 03/02/2016 | 11:30:30
z | 03/03/2016 | 07:30:30
So basically I want to build a query which will give unique values for 'usage_date', with max 'usage_hour'. How can I build this query?
First of all, you need to know how to do this in plain SQL, because Laravel's QueryBuilder is just a tool for building SQL-queries.
The task you described is kind of tricky and unfortunately there's no short and easy SQL query for that.
It can be done with window functions:
SELECT DISTINCT usage_date,
first_value(usage_hour) OVER (PARTITION BY usage_date ORDER BY usage_hour DESC) as usage_hour,
first_value(data) OVER (PARTITION BY usage_date ORDER BY usage_date DESC, usage_hour DESC) as data
FROM t
(sqlfiddle example)
With QueryBuilder it will look like this:
DB::table('t')
->distinct()
->select([
'usage_date',
DB::raw('first_value(usage_hour) OVER (PARTITION BY usage_date ORDER BY usage_hour DESC) as usage_hour'),
DB::raw('first_value(data) OVER (PARTITION BY usage_date ORDER BY usage_date DESC, usage_hour DESC) as data')
])
->get()
Or it can be done with a subquery (which is inefficient and not cool):
SELECT usage_date, max(usage_hour) as usage_hour,
(SELECT data FROM t AS t2
WHERE t2.usage_date = t.usage_date AND t2.usage_hour = max(t.usage_hour)
LIMIT 1) AS data
FROM t
GROUP BY usage_date
If anyone knows a method without subqueries and window functions, please let me know.
Try this and let see how it goes
$table = \DB::table('table name')->distinct('usage_date')->groupBy('usage_date')->orderBy('usage_hour','desc')->get();

SQL Select Records ONLY When a Column Value Is In More Than Once

I have a stored procedure in SQL Server, I am trying to select only the records where a column's value is in there more than once, This may seem a bit of an odd request but I can't seem to figure it out, I have tried using HAVING clauses but had no luck..
I want to be able to only select records that have the ACCOUNT in there more than once, So for example:
ACCOUNT | PAYDATE
-------------------
B066 | 15
B066 | OUTSTAND
B027 | OUTSTAND <--- **SHOULD NOT BE IN THE SELECT**
B039 | 09
B039 | OUTSTAND
B052 | 09
B052 | 15
B052 | OUTSTAND
BO27 should NOT show in my select, and the rest of the ACCOUNTS should.
here is my start and end of the Stored Procedure:
Select * from (
*** SELECTS ARE HERE ***
) X where O_STAND <> 0.0000
group by X.ACCOUNT, X.ACCT_NAME , X.DAYS_CR, X.PAYDATE, X.O_STAND
order by X.ACCOUNT
I have been struggling with this for a while, any help or advice would be appreciated. Thank you in advance.
you could replace the first string with
Select *, COUNT(*) OVER (PARTITION BY ACCOUNT) cnt FROM (
and then wrap your query as subquery once more
SELECT cols FROM ( query ) q WHERE cnt>1
Yes, the having clause is for solving exactly this kind of tasks. Basically, it's like where, but allows to filter not only by column values, but also by aggregate functions' results:
declare #t table (
Id int identity(1,1) primary key,
AccountId varchar(20)
);
insert into #t (AccountId)
values
('B001'),
('B002'),
('B015'),
('B015'),
('B002');
-- Get all rows for which AccountId value is encountered more than once in the table
select *
from #t t
where exists (
select 0
from #t h
where h.AccountId = t.AccountId
group by h.AccountId
having count(h.AccountId) > 1
);

Max Value with unique values in more than one column

I feel like I'm missing something really obvious here.
Using T-SQL/SQL-Server:
I have unique values in more than one column but want to select the max version based on one particular column.
Dataset:
Example
ID | Name| Version | Code
------------------------
1 | Car | 3 | NULL
1 | Car | 2 | 1000
1 | Car | 1 | 2000
Target status: I want my query to only select the row with the highest version value. Running a MAX on the version column pulls all three because of the distinct values in the 'Code' column:
SELECT ID
,Name
,MAX(Version)
,Code
FROM Table
GROUP BY ID, Name, Code
The net result is that I get all three entries as per the data set due to the unique values in the Code column, but I only want the top row (Version 3).
Any help would be appreciated.
You need to identify the row with the highest version as 1 query and use another outer query to pull out all the fields for that row. Like so:
SELECT t.ID, t.Name, GRP.Version, t.Code
FROM (
SELECT ID
,Name
,MAX(Version) as Version
FROM Table
GROUP BY ID, Name
) GRP
INNER JOIN Table t on GRP.ID = t.ID and GRP.Name = t.Name and GRP.Version = t.Version
You can also use row_number() to do this kind of logic, for example like this:
select ID, Name, Version, Code
from (
select *, row_number() over (order by Version desc) as RN
from Table1
) X where RN = 1
Example in SQL Fiddle
add the top statment to force the return of a single row. Also add the order by notation
SELECT top 1 ID
,Name
,MAX(Version)
,Code
FROM Table
GROUP BY ID, Name, Code
order by max(version) desc

Resources