Getting value from MAX(Date) Row in SQL Server - sql

I am trying to get the last supplier of an item, by using the MAX function. What I am trying to achieve is showing what the supplier name was for the row with the MAX(Date) for all the stock items (shown below as account links).
The code I am using bring up multiple dates for the same accountlink, and I am struggling to see why. My code is:
SELECT
MAX(TxDate) AS Date,
ST.AccountLink,
V.Account AS Supplier
FROM _bvSTTransactionsFull AS ST
JOIN Vendor V on ST.DrCrAccount = V.DCLink
WHERE Module = 'AP'
AND Id = 'OGrv'
GROUP BY ST.AccountLink, V.Account
ORDER BY AccountLink
But my results look like the below

Try this out
select AccountLink,Supplier,date from(SELECT
ST.AccountLink,
V.Account AS Supplier,
TxDate as [date],
row_number()over(partition by ST.AccountLink order by TxDate desc)rownum
FROM _bvSTTransactionsFull AS ST
JOIN Vendor V on ST.DrCrAccount = V.DCLink
WHERE Module = 'AP'
AND Id = 'OGrv')t
where t.rownum = 1
The group by has been removed and ranking function is used to achieve the output

You need a simple subquery to select the last supplier.
select X.supplier as LastSupplier, X.Date as lastDate, X.AccountLink
from _bvSTTransactionsFull X
where X.Date = (select max(date)
from _bvSTTransactionsFull Y
where Y.AccountLink=X.AccountLink)
The subquery extracts the last date for any accountLink, so you can use it on the outer where condition.

Related

Postgres - Pick 1 max row instead of all max rows in the same month on a LOD (group by)

Hi have a data set which has product, site, station, date and some numerical fields such as sn_count, blob etc.
Within every combination of product, site and station, if there are multiple entries for the same month from different dates, I want to only pick one row with max sn count in that month.
The code I have right now is working for the most part. It is filtering out rows with lesser sn counts in that month. But it gives me all rows with the same max sn count. Whereas, I just want 1 from a month.
This is my code:
FROM insight_info_temp a
INNER JOIN
(
SELECT distinct b.product_code,b.site_name,b.station_type,to_char(b.date_b, 'YYYY-MM') as date_new,
MAX(dist_sn_count_at_blob) as max_sn
FROM insight_info_temp b
GROUP BY b.product_code,b.site_name,b.station_type,to_char(b.date_b, 'YYYY-MM')
) b
ON a.product_code = b.product_code and
a.site_name = b.site_name and
a.station_type = b.station_type and
to_char(a.date_b, 'YYYY-MM') = b.date_new
AND a.dist_sn_count_at_blob = b.max_sn
where a.product_code = 'D00'
and a.site_name = 'F00' and a.station_type = 'A00';
This is the result I have:
The highlighted rows have the same sn count and is the max sn count for that month.
I however, only want one of these rows. Not both.
My guess is that you have two observations with the same dist_sn_count_at_blob.
This is a candidate for PostgreSQL's distinct on.
Please try something like this:
select distinct on (product_code, site_name, station_type,
to_char(date_b, 'YYYY-MM'))
dist_sn_count_at_blob, last_updated_at_pkey, <other columns>
from insight_info_temp
where a.product_code = 'D00'
and a.site_name = 'F00'
and a.station_type = 'A00'
order by product_code, site_name, station_type,
to_char(date_b, 'YYYY-MM'), dist_sn_count_at_blob desc;

Pivot rows to columns

I need to create one master table to present in reporting services, but i have an issue on how to combine the data.
To be more specific, i have one table named "Reservaciones" which store information from residences that have been reserved in certain dates.
Now for example, I´m grouping the information by this fields:
R.ClaTrab AS WorkerId
R.ClaUbicacion AS UbicationID
R.ClaEstancia AS ResidenceID
R.FechaIni AS InitialDay
R.FechaFin AS LastDay
And the result is First result**
As you see in the picture we have two rows duplicated, the number four and number five to be exact.
So far this is my code
SELECT
R.ClaTrab AS WorkerId,
MAX(E.NomEstancia) AS ResidenceName,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay
FROM Reservaciones AS R
INNER JOIN Estancias AS E ON E.ClaEstancia = R.ClaEstancia
WHERE E.ClaUbicacionEst = 3
GROUP BY R.ClaTrab,R.ClaUbicacion, R.ClaEstancia, R.FechaIni, R.FechaFin
ORDER BY R.FechaIni
I Want the result to be like this desire result, but i dont know how to do it, i have tried PIVOT but i cant get the result i want it.
If u need more information please, ask me.
thank you very much.
SOLUTION:
What i did is use the ROW NUMBER() and OVER PARTITION BY to create a group of workers in the same residence, then PIVOT the result in new columns.
SNIPPET
SELECT * FROM(
SELECT
MAX(E.NomEstancia) AS ResidenceName,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
T.NomTrab AS Worker,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
ROW_NUMBER() OVER(PARTITION BY FechaIni,FechaFin, R.ClaUbicacion, R.ClaEstancia ORDER BY T.NomTrab) AS GUEST
FROM Reservaciones AS R
INNER JOIN Estancias AS E ON E.ClaEstancia = R.ClaEstancia
INNER JOIN Trabajadores AS T ON T.ClaTrab = R.ClaTrab
WHERE E.ClaUbicacionEst = 3
GROUP BY T.NomTrab, R.ClaUbicacion, R.ClaEstancia, R.FechaIni,R.FechaFin) AS ONE
PIVOT( MAX(Worker) FOR GUEST IN ([1],[2],[3])) AS pvt
In the new query I added a new join to obtain the name of the workers
Since there can only be 2 workers, you can use Min and Max.
with cte as(
SELECT
R.ClaTrab AS WorkerId,
MAX(E.NomEstancia) AS ResidenceName,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay
FROM
Reservaciones AS R
INNER JOIN
Estancias AS E
ON E.ClaEstancia = R.ClaEstancia
WHERE
E.ClaUbicacionEst = 3
GROUP BY
R.ClaTrab,
R.ClaUbicacion,
R.ClaEstancia,
R.FechaIni,
R.FechaFin),
cte2 as(
select
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay
,Worker1 = max(WorkerId)
,Worker2 = min(WorkerId)
from
cte
group by
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay)
select
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay
,Worker1
,Worker2 = case when Worker1 = Worker2 then NULL else Worker2 end
from
cte2
ONLINE DEMO WITH PARTIAL TEST DATA

Group by not working to get count of a column with other max record in sql

I have a table named PublishedData, see image below
I'm trying to get the output like, below image
I think you can use a query like this:
SELECT dt.DistrictName, ISNULL(dt.Content, 'N/A') Content, dt.UpdatedDate, mt.LastPublished, mt.Unpublished
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY DistrictName ORDER BY UpdatedDate DESC, ISNULL(Content, 'zzzzz')) seq
FROM PublishedData) dt
INNER JOIN (
SELECT DistrictName, MAX(LastPublished) LastPublished, COUNT(CASE WHEN IsPublished = 0 THEN 1 END) Unpublished
FROM PublishedData
GROUP BY DistrictName) mt
ON dt.DistrictName = mt.DistrictName
WHERE
dt.seq = 1;
Because I think you use an order over UpdatedDate, Content to gain you two first columns.
Check out something like this (I don't have your tables, but you will get the idea where to follow with your query):
SELECT DirectName,
MAX(UpdatedDate),
MAX(LastPublished),
(
SELECT COUNT(*)
FROM PublishedData inr
WHERE inr.DirectName = outr.DirectName
AND inr.IsPublished = 0
) AS Unpublished
FROM PublishedData outr
GROUP BY DirectName
We should required a unique identity for that required output in PublishedData Table,Because We can't get the Latest content from given Schema.
If you want data apart from content like DistictName,updatedDate,LastPublishedDate and count of Unpublished records ,Please use Query given below :
select T1.DistrictName,T1.UpdatedDate,T1.LastPublished,T2.Unpublished from
(select DistrictName,Max(UpdateDate) as UpdatedDate,Max(LastPublished) as LastPublished from PublishedData group by DistrictName) T1
inner join
(select DistrictName,count(IsPublished) as Unpublished from PublishedData where isPublished=0 group by DistrictName) T2 ON T1.DistrictName=T2.DistrictName ORDER BY T2.Unpublished DESC

SELECT DISTINCT not ordering correctly

I have the following SQL statement:
SELECT DISTINCT ON (watch.url)
watch.url, watch.name, user_url.frequency, watch.selector, price.date
FROM watch
JOIN user_url on user_url.url = watch.url
LEFT JOIN price on price.url = watch.url
WHERE (1400575234 > price.date + user_url.frequency)
OR price.date is null
ORDER BY watch.url, price.date DESC
Where 1400575234 is the current unix timestamp. The table price holds the price of an item at different time intervals, one per row.
Currently this query will return me all the items because at some point they have had an entry which is less than the current date. Whereas I am only looking at grabbing the URL's whose price.date is less than the current time but I only want to match against the highest date for the url in the price table.
I think I need to run the order by before the select distinct works. Does anyone have any ideas?
(Hope this makes sense)
You could try using a window function instead:
SELECT url, name, frequency, selector, date
FROM (
SELECT watch.url, watch.name, user_url.frequency, watch.selector, price.date,
row_number() over (partition by watch.url order by price.date desc) as rn
FROM watch
JOIN user_url on user_url.url = watch.url
LEFT JOIN price on price.url = watch.url
WHERE (1400575234 > price.date + user_url.frequency)
OR price.date is null
) t
WHERE rn = 1
ORDER BY url, date;
Btw: date is a horrible name for a column
I've seemed to of solved it using the following
SELECT DISTINCT ON (watch.url)
watch.url, watch.name, user_url.frequency, watch.selector, p.date
FROM watch
JOIN user_url on user_url.url = watch.url
LEFT JOIN (
SELECT max(price.date) as date, url FROM price GROUP BY url
) as p ON p.url = watch.url
WHERE 1400575234 > p.date + user_url.frequency
ORDER BY watch.url
Thanks for everyones help. If you can see anyway to make the query more efficient please let me know.

How to pass value to and join correlated query having WITH clause?

I need to pass from one select value to another one to get the calculation done and join the results but having problem with this "with" clause sub query.
This one calculates balance from supplied number loan_id from the second query
WITH my_select (balance, type) As
(
select sum(amount_o-amount_h) as balance, type
from decret d
where d.idnumber = **loan_id**
and d.DATE_D <= '2013-10-31'
and type in (1,2,3,4,11,12,13,18,20,25)
group by type
having sum(amount_o-amount_h) <> 0
)
select sum(balance) FROM my_select //just returns client balance
And this one selects clients data and I want for every client add the balance also to the result calculated in first query.
SELECT *, /*balance*/ from clients
where **loan_id** in (select LoanNum
from NumsFromEx)
How to join them together? (I have simplified a little bit queries to show it cleaner)
Given the sample queries, the following should work:
WITH cteBalances AS
(
SELECT loan_id, SUM(amount_o-amount_h) AS balance
FROM decret d
WHERE d.DATE_D <= '2013-10-31'
AND type IN (1,2,3,4,11,12,13,18,20,25)
GROUP BY loan_id
)
SELECT c.*, b.balance
FROM clients c
LEFT JOIN cteBalances b ON b.loan_id = c.loan_id
WHERE loan_id IN (SELECT LoanNum
FROM NumsFromEx)