Trying "over partition by" and its not working - sql

This works:
select top 100 cti.tradingitemid, pe.pricingDate, pe.priceClose, pe.adjustmentFactor, cc.countryId, cc.companyId
from ciqcompany cc
join ciqfinperiod cfp on cfp.companyid=cc.companyid
join ciqfininstance cfi on cfi.financialperiodid=cfp.financialperiodid
join ciqsecurity cs on cs.companyid = cc.companyid
join ciqtradingitem cti on cti.securityid=cs.securityid
join ciqPriceEquity pe on pe.tradingItemId=cti.tradingItemId
where pe.pricingDate >= '1974-12-31 00:00:00.000' and pe.pricingDate <'1975-02-01 00:00:00.000' and cc.countryId = 213
order by cc.companyId
The problem is that I get hundreds of lines for the same companyID. I just want one per companyID, the first one would work fine.
I've been looking around and this is the best I could come up with:
select *
FROM (
Select cti.tradingitemid,
pe.pricingDate,
pe.priceClose,
pe.adjustmentFactor,
cc.countryId
Row_number() OVER (PARTITION BY cc.companyId ORDER BY pe.pricingDate) RN
from ciqcompany cc
join ciqfinperiod cfp on cfp.companyid=cc.companyid
join ciqfininstance cfi on cfi.financialperiodid=cfp.financialperiodid
join ciqsecurity cs on cs.companyid = cc.companyid
join ciqtradingitem cti on cti.securityid=cs.securityid
join ciqPriceEquity pe on pe.tradingItemId=cti.tradingItemId
where pe.pricingDate >= '1974-12-31 00:00:00.000' and pe.pricingDate <'1975-02-01 00:00:00.000' and cc.countryId = 213
order by cc.companyId
)
Where rn = 1
The syntax at Row_number() is throwing it off, but to me it looks like other examples I see.
Any ideas would be much appreciated.

Would this work?
SELECT *
FROM (
.....
---- missing comma after cc.countryId
---- remove order by
) A
WHERE
A.RN = 1
ORDER BY cc.companyId

Three things:
Your subquery needs a table alias.
The subquery cannot contain order by.
And you need a comma before row_number().
So:
select t.*
from ( Select cti.tradingitemid,
pe.pricingDate,
pe.priceClose,
pe.adjustmentFactor,
cc.countryId,
Row_number() OVER(PARTITION BY cc.companyId ORDER BY pe.pricingDate) RN
from ciqcompany cc
join ciqfinperiod cfp on cfp.companyid=cc.companyid
join ciqfininstance cfi on cfi.financialperiodid=cfp.financialperiodid
join ciqsecurity cs on cs.companyid = cc.companyid
join ciqtradingitem cti on cti.securityid=cs.securityid
join ciqPriceEquity pe on pe.tradingItemId=cti.tradingItemId
where pe.pricingDate >= '1974-12-31' and pe.pricingDate < '1975-02-01' and
cc.countryId = 213
) t
order by cc.companyId;
I removed the time component from the dates. It is not needed for the logic.

Related

Count with row_number function SQL CTE

I have the below CTEs that work perfectly, but I want to count the "cl.memb_dim_id" by "cl.post_date" but I am not sure how to do that? When adding in the count function I get an error that highlights the ' row number' so I am assuming I cant have both order and group together ????
WITH
DATES AS
(
select to_date('01-jan-2017') as startdate,to_date('02-jan-2017') as enddate
from dual
),
Claims as (select distinct
cl.memb_dim_id,
row_number () over (partition by cl.Claim_number order by cl.post_date desc) as uniquerow,
cl.Claim_number,
cl.post_date,
ct.claim_type,
ap.claim_status_desc,
dc.company_desc,
dff.io_flag_desc,
pr.product_desc,
cl.prov_dim_id,
cl.prov_type_dim_id
from dw.fact_claim cl
inner join dates d
on 1=1
and cl.post_date >= d.startdate
and cl.post_date <= d.enddate
and cl.provider_par_dim_id in ('2')
and cl.processing_status_dim_id = '1'
and cl.company_dim_id in ('581','585','586','589','590','591','588','592','594','601','602','603','606','596','598','597','579','599','578','577','573','574','576','575')
left join dw.DIM_CLAIM_STATUS ap
on cl.claim_status_dim_id = ap.claim_status_dim_id
left join dw.dim_claim_type ct
on cl.claim_type_dim_id = ct.claim_type_dim_id
and cl.claim_type_dim_id in ('1','2','6','7')
left join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
left join dw.DIM_IO_FLAG dff
on cl.io_flag_dim_id = dff.io_flag_dim_id
left join dw.dim_product pr
on cl.product_dim_id = pr.product_dim_id
)
Select * from claims where uniquerow ='1'
First, does this work?
count(cl.memb_dim_id) over (partition by cl.Claim_number, cl.post_date) as cnt,
Second, it is strange to be using analytic functions with select distinct.

How to remove duplicate entries in my query?

The following code gives me multiple lines since there can be more than one Cust_Edit_Log.Edit_Timestamp per Alarm Account. There is no other way for a duplicate to occur. How do I only get the result with the earliest Cust_Edit_Log.Edit_Timestamp date? Thank you in advance for any help you can provide.
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User'
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
Order By
AR_Customer.Customer_Number ASC
Use Partition BY:
SELECT
X.*
FROM
(
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User',
ROW_NUMBER() OVER(Partition BY AR_Customer_System.Alarm_Account,Cust_Edit_Log.Edit_Timestamp ORDER BY AR_Customer_System.Alarm_Account) AS PartNO
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
)X
WHERE X.PartNo=1
Order By X.Customer_Number ASC
One method uses row_number():
Left Outer Join
(select lp.*,
row_number() over (partition by lp.Customer_Id
order by Edit_Timestamp asc
) as seqnum
from CQB_Log_Parse lp
) Cust_Edit_Log
on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id and
seqnum = 1
Maybe try with MIN(Cust_Edit_Log.Edit_Timestamp)
You can try using as below:
;with cte as (
Select
AR_Customer.Customer_Number As 'Customer_Number',
AR_Customer.Customer_Name As 'Customer_Name',
AR_Customer_System.Alarm_Account As 'Alarm_Account',
AR_Customer_Site.Address_1 As 'Site_Address_1',
Cust_Edit_Log.UserComments As 'Edit_Log_Cust_User_Comments',
Cust_Edit_Log.Edit_Timestamp As 'Edit_Log_Cust_Timestamp',
Cust_Edit_Log.UserCode As 'Edit_Log_Cust_User'
,row_number() over(partition by AR_Customer.Customer_Number order by Cust_Edit_Log.Edit_Timestamp) as rownum
From
AR_Customer
Inner JOIN AR_Customer_Site On AR_Customer.Customer_Id = AR_Customer_Site.Customer_Id
Left Outer JOIN AR_Customer_System On AR_Customer_Site.Customer_Site_Id = AR_Customer_System.Customer_Site_Id
Left Outer Join CQB_Log_Parse Cust_Edit_Log on AR_Customer.Customer_Id = Cust_Edit_Log.Customer_Id
Where
AR_Customer.Customer_Id <> 1 And
(AR_Customer_System.Alarm_Account Like 'IN%' And
Cust_Edit_Log.UserComments Like 'Edited Customer System IN%')
--Order By
--AR_Customer.Customer_Number ASC
)
select * from cte where rownum = 1
order by AR_Customer.Customer_Number ASC

Limiting result sets by future date - SQL

The Query below produces a record for each Entry in the SP_ScheduleEvent Table.
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
INNER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
INNER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
I want to limit the result set by the nearest future EventDateTime.
So per material name i would like to see one EventDateTime, which should be the nearest future date to the current time.
And lastly, a record may not exist in the SP_ScheduleEvent table for a particular materialname, in which case there should be null returned for the EventDateTime column
SQLFiddle
How would i go about doing this?
First, your LEFT JOIN is immaterial, because the subsequent joins make it an INNER JOIN. Either use LEFT JOIN throughout the FROM statement or switch to INNER JOIN.
I think you can use ROW_NUMBER():
SELECT t.*
FROM (SELECT m.MaterialId, m.MaterialName, m.MaterialTitle, se.EventDateTime,
ROW_NUMBER() over (PARTITION BY m.MaterialId OVER se.EventDateTime DESC) as seqnum
FROM GB_Material m INNER JOIN
SP_ScheduleEvent se
on se.MaterialName = m.MaterialName INNER JOIN
SP_Schedule s
on s.ScheduleID = se.ScheduleID INNER JOIN
GB_Channel c
on c.ChannelID = s.ChannelID
WHERE se.EventDateTime > getdate() AND
(LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%')
) t
WHERE seqnum = 1
ORDER BY se.EventDateTime;
Use the ROW_NUMBER() function:
WITH cte AS (
SELECT m.MaterialId, m.MaterialTitle, se.EventDateTime, c.ChannelName,
ROW_NUMBER() OVER (PARTITION BY m.MaterialId ORDER BY EventDateTime ASC) AS rn
FROM GB_Material m
LEFT OUTER JOIN SP_ScheduleEvent se on se.MaterialName = m.MaterialName
LEFT OUTER JOIN SP_Schedule s on s.ScheduleID = se.ScheduleID
LEFT OUTER JOIN GB_Channel c on c.ChannelID = s.ChannelID
WHERE LOWER(m.MaterialName) like '%foo%' OR LOWER(m.MaterialTitle) like '%foo%'
AND se.EventDateTime > GETDATE()
)
SELECT * FROM cte
WHERE rn=1

SQL - Using Subquery with Aggregate Function

I'm trying to return the last time entry posted for a particular client, and the case (matter) number associated to that entry. The relationship is one client has many matters, and one matter has many time entries.
I have the code below, but it obviously returns all the matters and not just the one associated to the time entry. I understand why, but tie myself in knots when trying to correct it. Any help much appreciated.
select c.CLIENT_CODE,
c.CLIENT_NAME,
c.OPEN_DATE,
mp.EMPLOYEE_NAME,
MAX(tt.TRAN_DATE)[Last Time],
m.MATTER_NUMBER
from HBM_CLIENT c
join HBM_MATTER m
on m.CLIENT_UNO=c.CLIENT_UNO
left join TAT_TIME tt
on tt.MATTER_UNO=m.MATTER_UNO
left join HBM_PERSNL mp
on mp.EMPL_UNO=c.RESP_EMPL_UNO
where c.STATUS_CODE = 'Targ'
group by c.CLIENT_CODE,
c.CLIENT_NAME,
c.OPEN_DATE,
mp.EMPLOYEE_NAME,
m.MATTER_NUMBER
order by OPEN_DATE
Completely untested but in the right direction
select
<whatever>
from
HBM_CLIENT c
join HBM_MATTER m on
m.CLIENT_UNO = c.CLIENT_UNO
join TAT_TIME tt on
tt.MATTER_UNO = m.MATTER_UNO AND
tt.tran_date = (
select max(tran_date)
from TAT_TIME
where matter_uno = m.matter_uno)
where
m.CLIENT_UNO = ? and
c.STATUS_CODE = 'Targ'
One way to do this is using row_number(). I think the following will do what you want:
select c.CLIENT_CODE, c.CLIENT_NAME, c.OPEN_DATE, mp.EMPLOYEE_NAME,
tt.TRAN_DATE as [Last Time], m.MATTER_NUMBER
from HBM_CLIENT c join
(select m.*, tt.TRAN_DATE,
row_number() over (partition by m.CLIENT_UNO
order by tt.TRAN_DATE desc
) as seqnum
from HBM_MATTER m LEFT JOIN
TAT_TIME tt
ON tt.MATTER_UNO = m.MATTER_UNO
) m
ON m.CLIENT_UNO = c.CLIENT_UNO and seqnum = 1 left join
HBM_PERSNL mp
on mp.EMPL_UNO=c.RESP_EMPL_UNO
where c.STATUS_CODE = 'Targ';
I don't think you need the group by, unless the other joins create duplicates.

How to have distinct data in SQL using MAX on inner joined tables

I used this code to get distinct columns according to the max update_date. But still I get about 4 or 5 status_ids for the same tel_number. I want the max update date to take only the last date...which is not currently done by my code. Can someone please help me
SELECT DISTINCT t.Tel_Number,
t.Entity_ID,
t.Datasource,
t.Datasource_Number,
t.UpdateDate,
t.DataDate,
t.Telephone_ID,
t.Status_Id,
t.DateInserted,
t.ProcessName,
c.Status_Id AS CurrentCe_Status_ID,
s.StatusType AS CurrentCe_StatusType,
s.Description AS CurrentCe_Status_Description,
MAX(c.Update_Date) AS CurrentCe_Status_Date
FROM
Wrk.dbo.tel_trsn t WITH (NOLOCK) INNER JOIN CrWec.dbo.teldet d WITH (NOLOCK)
ON d.Tel_Number = t.Tel_Number
AND d.Entity_Id = t.Entity_ID
INNER JOIN CrWec.dbo.status c WITH (NOLOCK)
ON c.Entity_Id = t.Entity_ID
INNER JOIN CrWec.dbo.statusType s WITH (NOLOCK)
ON s.Status_Id = c.Status_Id
GROUP BY t.Tel_Number,
t.Entity_ID,
t.Datasource,
t.Datasource_Number,
t.UpdateDate,
t.DataDate,
t.Telephone_ID,
t.Status_Id,
t.DateInserted,
t.ProcessName,
c.Status_Id,
s.StatusType,
s.Description
Since you didn't specify what any of the keys were, I did the best I could with the query. In reality, if your key values are just Tel_Number, Entity_ID, Datasource, then you'd only need to partition on those 3 columns in the ROW_NUMBER function (or however many is necessary).
;with MaxUpdateDate as (
SELECT t.Tel_Number,
t.Entity_ID,
t.Datasource,
t.Datasource_Number,
t.UpdateDate,
t.DataDate,
t.Telephone_ID,
t.Status_Id,
t.DateInserted,
t.ProcessName,
c.Status_Id AS CurrentCe_Status_ID,
s.StatusType AS CurrentCe_StatusType,
s.Description AS CurrentCe_Status_Description,
c.Update_Date AS CurrentCe_Status_Date,
ROW_NUMBER() OVER (
PARTITION BY
t.Tel_Number,
t.Entity_ID,
t.Datasource,
t.Datasource_Number,
t.UpdateDate,
t.DataDate,
t.Telephone_ID,
t.Status_Id,
t.DateInserted,
t.ProcessName,
c.Status_Id,
s.StatusType,
s.Description
ORDER BY
c.Update_Date DESC) as 'RowNum'
FROM
Wrk.dbo.tel_trsn t WITH (NOLOCK)
INNER JOIN CrWec.dbo.teldet d WITH (NOLOCK)
ON d.Tel_Number = t.Tel_Number
AND d.Entity_Id = t.Entity_ID
INNER JOIN CrWec.dbo.status c WITH (NOLOCK)
ON c.Entity_Id = t.Entity_ID
INNER JOIN CrWec.dbo.statusType s WITH (NOLOCK)
ON s.Status_Id = c.Status_Id
)
SELECT
*
FROM
MaxUpdateDate
WHERE
RowNum = 1