Most Recent Data - sql-server

I have a schema that looks like this.
Using the recordings table , query the most recent data in the database for each entityid/accid/month combination (Main Table is the main table)

use row_number()
select * from
(
select *,row_number() over(partition by entid, accid, month order by timestamp desc) as rn
from recordings a inner join maintable b on a.logid=b.logid
)A where rn=1

use row_number()
select * from
(
select m.*, row_number() over(partition by acctid,entid,month order by timestamp desc) rn
from maintable m join racordings r on m.logid=r.logid
) a where a.rn=1

Here's your query.
select * from
(select m.*, r.*, e.*, a.*, row_number() over(partition by a.AcctID, e.EntID, Month order by r.TimeStamp desc) row_num
from maintable m
inner join racordings r on m.LogID = r.LogID
inner join Entities e on e.EntID = m.EntID
inner join AccInfo a on a.AcctID = m.AcctID
) t1
where t1.row_num = 1

Related

SQL Simple Join with two tables, but one is random

I am stuck with this. I have a simple set-up with two tables. One table is holding emailaddresses one table is holding vouchercodes. I want to join them in a third table, so that each emailaddress has one random vouchercode.
Unfortunatly I am stuck with this as there are no identic Ids to match both values. What I have so far brings no result:
Select
A.Email
B.CouponCode
FROM Emailaddresses as A
JOIN CouponCodes as B
on A.Email = B.CouponCode
A hint would be great as search did not bring me any further yet.
Edit -
Table A (Addresses)
-------------------
Column A | Column B
-------------------------
email1#gmail.com True
email2#gmail.com
email3#gmail.com True
email4#gmail.com
Table B (Voucher)
-------------------
ABCD1234
ABCD5678
ABCD9876
ABCD5432
Table C
-------------------------
column A | column B
-------------------------
email1#gmail.com ABCD1234
email2#gmail.com ABCD5678
email3#gmail.com ABCD9876
email4#gmail.com ABCD5432
Sample Data:
While joining without proper keys is not a good solution, for your case you can try this. (note: not tested, just a quick suggestion)
;with cte_email as (
select row_number() over (order by Email) as rownum, Email
from Emailaddresses
)
;with cte_coupon as (
select row_number() over (order by CouponCode) as rownum, CouponCode
from CouponCodes
)
select a.Email,b.CouponCode
from cte_email a
join cte_coupon b
on a.rownum = b.rownum
You want to randomly join records, one email with one coupon each. So create random row numbers and join on these:
select
e.email,
c.couponcode
from (select t.*, row_number() over (order by newid()) as rn from emailaddresses t) e
join (select t.*, row_number() over (order by newid()) as rn from CouponCodes t) c
on c.rn = e.rn;
Give a row number for both the tables and join it with row number.
Query
;with cte as(
select [rn] = row_number() over(
order by [Column_A]
), *
from [Table_A]
),
cte2 as(
select [rn] = row_number() over(
order by [Column_A]
), *
from [Table_B]
)
select t1.[Column_A] as [Email_Id], t2.[Column_A] as [Coupon]
from cte t1
join cte2 t2
on t1.rn = t2.rn;
Find a demo here

How to select a specific range from first row with each id MSSQL

I have created a table in html to display first rows of each id and allow user to select specific range they want to see, but not sure how I can write it in query.
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT * FROM results WHERE [RN] = 1;
UPDATED
I have tried to inject two ROW_NUMBER(), but what I received is row 10 and row 25 and they are first rows of some specific id.
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN],
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT * FROM results WHERE [RN] = 1 AND BETWEEN [R]>10 AND [R]<25
What I am really looking for is select a specific range from all the first row for each id.
FINAL
Thank to McGlothlin, finally I solve it. What I need is a nested CTE.
With First_CTE as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
),
results AS
(
SELECT k.*,
ROW_NUMBER() OVER (ORDER BY k.ID DESC) AS [R]
FROM First_CTE AS k WHERE k.[RN] = 1
)
SELECT * FROM results WHERE [R]>10 AND [R]<25
The problem lies in this line:
ROW_NUMBER() OVER I.ID AS [R]
I think what you meant was:
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
This is assuming you want to give it a row count over every row that is returned in the CTE. The ROW_NUMBER() function requires an ORDER BY to be specified, and the OVER clause would still require parentheses if you were using a function like SUM that could be used without an ORDER BY.
Edit: Based on your comment, it sounds like what you're looking for is an OFFSET. In that case you would remove the second ROW_NUMBER and include something like this:
ORDER BY ID OFFSET 10 ROWS FETCH FIRST 15 ROWS ONLY
This returns rows 11 to 25, sorted by ID.
Since the OFFSET syntax doesn't work in SQL Server 2008, you should do something like this as your end result:
With results as
(
i.*,
ROW_NUMBER() OVER (PARTITION BY i.ID ORDER BY I.ID DESC) AS [RN]
ROW_NUMBER() OVER (ORDER BY I.ID) AS [R]
FROM HolidayList AS I
INNER JOIN (
SELECT ID, MIN(CreateDate) FROM HolidayList GROUP BY ID
)
AS j ON i.ID = j.ID AND i.CreateDate = j.CreateDate
)
SELECT *
FROM results
WHERE [RN] = 1
AND [R] BETWEEN 11 AND 25

How to get desired result by combining two CTE's with different tables?

I have two CTE's,firstly
;WITH CTE AS (SELECT A.*
, Row_NUMBER() Over (Partition by ID order by Date asc) RN
FROM TABLE A)
SELECT Sum(Weight) as IN_WT
FROM CTE
WHERE RN = 1 and name='dev1'
and then
;WITH CTE AS (SELECT B.*
, Row_NUMBER() Over (Partition by ID order by Date desc) RN1
FROM TABLE B)
SELECT Sum(Weight) AS out_wt
FROM CTE
WHERE RN1 = 1 and name='dev1'
Here we had two tablesTableA,TableB.We are getting In_wt from TableA and Out_wt from TableB.Now I had a requiremnt that the output should be combined and get in_wt,out_wt in single row from different tables and same name.I tried combining both the CTE's but didn't get the desired result.How can we do that?
Try this:
;WITH CTE1 AS (
SELECT name,
Row_NUMBER() Over (Partition by ID order by Date asc) RN
FROM TABLEA
), CTE2 AS (
SELECT name,
Row_NUMBER() Over (Partition by ID order by Date desc) RN
FROM TABLEB
)
SELECT (SELECT Sum(Weight) FROM CTE1 WHERE RN = 1 and name='dev1') AS IN_WT,
(SELECT Sum(Weight) FROM CTE2 WHERE RN = 1 and name='dev1') AS OUT_WT

Applying window function in one query without CTE

I have been searched in the net and trying to create a query that contains a window function without a CTE but I couldn't get the result and I need some help
this my query that I create with a CTE what I need is doing that in one query
;with cte(Gid, id, prod, orderdate, shipdate, ranking) as
(
select
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate,
rank() over (partition by p1.prod order by p1.id desc) ranking
from
shpro p1
inner join
shpro p2 on p1.id = p2.id
where
cast(p1.orderdate as DATE) > GETDATE()
and cast(p1.shipdate as DATE) < GETDATE() - 1
)
select *
from cte
where ranking = 1
Demo with some test data on how this works
select top (1) with ties
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate
from shpro p1 inner join shpro p2
on p1.id=p2.id
where cast(p1.orderdate as DATE)>GETDATE() and cast(p1.shipdate as DATE)<GETDATE()-1
order by
Rank() over (partition by p1.prod order by p1.id desc)
This works like below..
1.order by arranges all the rows based on their rank
2.Top 1 with ties options fetches all the rows which are tied
References:
T-SQL Querying (Developer Reference)
Below is some sample data to play with:
CREATE TABLE #TEST
(
Id INT,
Name VARCHAR(10)
)
Insert Into #Test
select 1,'A'
Union All
Select 1,'B'
union all
Select 1,'C'
union all
Select 2,'D'
select top 1 with ties id,name
from #test
order by row_number() over (partition by id order by id)
CTE can be translated directly into subquery. Yours query should look similar to following:
SELECT * FROM
(
select
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate,
rank() over (partition by p1.prod order by p1.id desc) ranking
from
shpro p1
inner join
shpro p2 on p1.id = p2.id
where
cast(p1.orderdate as DATE) > GETDATE()
and cast(p1.shipdate as DATE) < GETDATE() - 1
) CteAsSubquery
WHERE ranking = 1
Note alias CteAsSubquery is there (most common error).

RANK() Over Partition BY not working

When I run the code below the ROWID is always 1.
I need to the ID to start at 1 for each item with the same Credit Value.
;WITH CTETotal AS (SELECT
TranRegion
,TranCustomer
,TranDocNo
,SUM(TranSale) 'CreditValue'
FROM dbo.Transactions
LEFT JOIN customers AS C
ON custregion = tranregion
AND custnumber = trancustomer
LEFT JOIN products AS P
ON prodcode = tranprodcode
GROUP BY
TranRegion
,TranCustomer
,TranDocNo)
SELECT
r.RegionDesc
,suppcodedesc
,t.tranreason as [Reason]
,t.trandocno as [Document Number]
,sum(tranqty) as Qty
,sum(tranmass) as Mass
,sum(transale) as Sale
,cte.CreditValue AS 'Credit Value'
,RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.CreditValue)AS ROWID
FROM transactions t
LEFT JOIN dbo.Regions AS r
ON r.RegionCode = TranRegion
LEFT JOIN CTETotal AS cte
ON cte.TranRegion = t.TranRegion
AND cte.TranCustomer = t.TranCustomer
AND cte.TranDocNo = t.TranDocNo
GROUP BY
r.RegionDesc
,suppcodedesc
,t.tranreason
,t.trandocno
,cte.CreditValue
ORDER BY CreditValue ASC
EDIT
All the credit values with 400 must have the ROWID set to 1. And all the credit values with 200 must have the ROWID set to 2. And so on and so on.
Do you need something like this?
with cte (item,CreditValue)
as
(
select 'a',8 as CreditValue union all
select 'b',18 union all
select 'a',8 union all
select 'b',18 union all
select 'a',8
)
select CreditValue,dense_rank() OVER (ORDER BY item)AS ROWID from cte
Result
CreditValue ROWID
----------- --------------------
8 1
8 1
8 1
18 2
18 2
In your code replace
,RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.CreditValue)AS ROWID
by
,DENSE_RANK() OVER (ORDER BY cte.CreditValue)AS ROWID
You just don't have to use PARTITION, just DENSE_RANK() OVER (ORDER BY cte.CreditValue)
I think the problem is with the RANK() OVER (PARTITION BY clause
you have to partition it by item not by CreditValue
Try this
RANK() OVER (PARTITION BY cte.CreditValue ORDER BY cte.RegionDesc)AS ROWID
Edit: The issue here isn't actually the nesting of the subquery, it's potentially based on partition by having columns that truly make each row unique (or 1)
Rather than ranking within your complex query like this
select
rank() over(partition by...),
*
from
data_source
join table1
join table2
join table3
join table4
order by
some_column
Try rank() or row_number() on the resulting data set, not within it.
For example, using the query above, remove rank() and implement it this way:
select
rank() over(partition by...),
results.*
from (
select
*
from
data_source
join table1
join table2
join table3
join table4
order by
some_column
) as results

Resources