Select max date rows for unique key - sql

I have a select statement.
SELECT x.ndc_id
,z.attr_val AS trade_name
,x.quote_price
,x.eff_dt FROM contract_ndc_brg x
LEFT JOIN ndc_attr AS z ON z.field_id = 150
where contract_num_val = (
SELECT item_name
FROM [contract]
WHERE item_id = 184
)
Notice there are two rows with the same ndc_id. I want these results but only one result for each ndc_id which has the highest eff_dt.
I tried adding to the where clause:
SELECT x.ndc_id
,z.attr_val AS trade_name
,x.quote_price
,x.eff_dt FROM contract_ndc_brg x
LEFT JOIN ndc_attr AS z ON z.field_id = 150
where contract_num_val = (
SELECT item_name
FROM [contract]
WHERE item_id = 184
) and x.eff_dt = (select max(eff_dt) from contract_ndc_brg where contract_num_val = (
SELECT item_name
FROM [contract]
WHERE item_id = 184
))
I figured out the problem with this is that it is returning the max date for any row.
How can I fix what I am doing wrong?

ROW_NUMBER() is your friend:
with q as
(
SELECT x.ndc_id
,z.attr_val AS trade_name
,x.quote_price
,x.eff_dt
,row_number() over (partition by nc_id order by eff_dt desc) rn
FROM contract_ndc_brg x
LEFT JOIN ndc_attr AS z ON z.field_id = 150
where contract_num_val = (
SELECT item_name
FROM [contract]
WHERE item_id = 184
)
)
select nc_id, trade_name, quote_price, eff_dt
from q
where rn = 1

Related

How do I group by the most recent date?

I have a HISTORY table that has multiple rows for the same record and I am trying to get the latest (closest to today's date) record. I am attempting to group by the closest date but am having a difficult time. Please check out the query below and advise me.
SELECT DISTINCT *
FROM
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID
FROM etc.Complaint) AS Qry1
LEFT JOIN
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
FROM etc.Complaint
LEFT OUTER JOIN etc.History as o
ON SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1) AS Qry2
ON Qry1.Complaint_ID = Qry2.Complaint_ID
ORDER BY Qry1.Complaint_ID, MAX(Qry2.LastActionDate)
does this change help?
SELECT DISTINCT *
FROM
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID FROM etc.Complaint) AS Qry1
LEFT JOIN
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
FROM etc.Complaint
LEFT OUTER JOIN
(
SELECT SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) as hist_Complaint_ID , MAX(Action_Date) as Action_Date
FROM etc.History
WHERE Field_Name = 'Resolved_Ind'
GROUP BY SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15)
) as o
ON o.hist_Complaint_ID = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1) AS Qry2
ON Qry1.Complaint_ID = Qry2.Complaint_ID
ORDER BY Qry1.Complaint_ID, Qry2.LastActionDate
You can use ROW_NUMBER and a CTE to get it:
WITH cte AS (
SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
row_number() over (partition by etc.Complaint.Complaint_ID order by o.Action_Date desc) AS rn
FROM etc.Complaint
LEFT OUTER JOIN etc.History as o
ON SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1
)
SELECT * FROM cte
WHERE rn = 1

How to get only one value when you are getting multiple values against key in SQL

I have a SQL query. Below is the query
select
ID,
replace(replace(replace(replace([Name],',',''),'"',''),':',''),'?','') [Name] ,
replace(replace([Description],',',''),'"','') [Description],
[GUID],
Bussinesskey
from course
where COURSESTATUS = 'Published' and RETIREDTF = 0
and
bussinesskey in
(
...
)
and id in (
select c.id from course c
inner join COURSE_CUSTOMERENTITLEMENT cce on cce.COURSE_ID = c.ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cce.CUSTOMERENTITLEMENT_ID
where
ce.ENROLLMENTTYPE = 'Course'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
UNION
select c.id from course c
inner join COURSE_COURSEGROUP cg on cg.course_id = c.id
inner join COURSEGROUP_CUSTOMERENTITLEMENT cgce on cgce.COURSEGROUP_ID = cg.COURSEGROUP_ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cgce.CUSTOMERENTITLEMENT_ID
where
ce.ENROLLMENTTYPE = 'CourseGroup'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
)
order by name, id asc
When this query runs then I get the output like the following snapshot
You can see in the screen shot that I am getting 8 names of same type(Contracts). The last id of Contracts is 780697 which is the latest record that is added to database. Now i want that when my query runs then it gets only the latest record. Means instead of showing 8 name of Contarcts. Its only the show the latest one for each course name. Means for Contracts only record with ID 780697 is shown. If other courses has the same result then there latest Id record is shown only. How can I achieve this ?
Thanks
You can try following for achieving latest ID:-
select MAX(ID),
replace(replace(replace(replace([Name],',',''),'"',''),':',''),'?','') [Name] ,
replace(replace([Description],',',''),'"','') [Description],
[GUID],
Bussinesskey
from course
where COURSESTATUS = 'Published' and RETIREDTF = 0
and
bussinesskey in
(
...
)
and id in (
select c.id from course c
inner join COURSE_CUSTOMERENTITLEMENT cce on cce.COURSE_ID = c.ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cce.CUSTOMERENTITLEMENT_ID
where
ce.ENROLLMENTTYPE = 'Course'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
UNION
select c.id from course c
inner join COURSE_COURSEGROUP cg on cg.course_id = c.id
inner join COURSEGROUP_CUSTOMERENTITLEMENT cgce on cgce.COURSEGROUP_ID = cg.COURSEGROUP_ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cgce.CUSTOMERENTITLEMENT_ID
where
ce.ENROLLMENTTYPE = 'CourseGroup'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
)
group by [Name], [Description], [GUID], Bussinesskey
order by name, id asc
Here how I did this. I don't know how efficient this is but it's giving me what I am exactly wanting
select ID, [Name], [Description], [GUID], Bussinesskey from (
select row_number() over (partition by [Name] order by id desc) as row, t1.* from (
select
ID,
replace(replace(replace(replace([Name],',',''),'"',''),':',''),'?','') [Name] ,
replace(replace([Description],',',''),'"','') [Description],
[GUID],
Bussinesskey
from course
where COURSESTATUS = 'Published' and RETIREDTF = 0
and bussinesskey in (
'PSTOAS0314001',
...
'RECEAL0510019'
)
and id in (
select c.id from course c
inner join COURSE_CUSTOMERENTITLEMENT cce on cce.COURSE_ID = c.ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cce.CUSTOMERENTITLEMENT_ID
where ce.ENROLLMENTTYPE = 'Course'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
UNION
select c.id from course c
inner join COURSE_COURSEGROUP cg on cg.course_id = c.id
inner join COURSEGROUP_CUSTOMERENTITLEMENT cgce on cgce.COURSEGROUP_ID = cg.COURSEGROUP_ID
inner join CUSTOMERENTITLEMENT ce on ce.id = cgce.CUSTOMERENTITLEMENT_ID
where ce.ENROLLMENTTYPE = 'CourseGroup'
and ce.customer_id = 23753
and c.COURSESTATUS = 'Published' and c.RETIREDTF = 0
)
)t1
) t
where t.row=1
order by t.name, t.id asc
Thanks
;with Course as
(
Select 50000 ID, 'Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB1' BusinessKey
UNION
Select 60000 ID, 'Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB2' BusinessKey
UNION
Select 70000 ID, 'Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB3' BusinessKey
UNION
Select 80000 ID, 'Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB4' BusinessKey
UNION
Select 90000 ID, 'Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB5' BusinessKey
UNION
Select 40000 ID, 'NOT Contracts' Name, '<BLURB>' [Description], '<GUID>' GUID, 'ARB1' BusinessKey
),
Course_Group AS
(
Select 50000 Course_ID, 1 COURSEGROUP_ID
UNION
Select 60000 Course_ID, 1 COURSEGROUP_ID
UNION
Select 70000 Course_ID, 1 COURSEGROUP_ID
UNION
Select 80000 Course_ID, 1 COURSEGROUP_ID
UNION
Select 90000 Course_ID, 2 COURSEGROUP_ID
UNION
Select 40000 Course_ID, 1 COURSEGROUP_ID
),
CourseGroup_CustomerEntitlement AS
(
Select 1 COURSEGROUP_ID, 1 CUSTOMERENTITLEMENT_ID
--UNION
--Select 2 COURSEGROUP_ID, 2 CUSTOMERENTITLEMENT_ID
--UNION
--Select 2 COURSEGROUP_ID, 4 CUSTOMERENTITLEMENT_ID
),
Course_CustomerEntitlement AS
(
Select 50000 Course_ID, 3 CUSTOMERENTITLEMENT_ID
UNION
Select 60000 Course_ID, 3 CUSTOMERENTITLEMENT_ID
UNION
Select 90000 Course_ID, 3 CUSTOMERENTITLEMENT_ID
UNION
Select 40000 Course_ID, 4 CUSTOMERENTITLEMENT_ID
),
CustomerEntitlement AS
(
Select 1 ID, 23753 Customer_ID, 'CourseGroup' ENROLLMENTTYPE
UNION
Select 2 ID, 7 Customer_ID, 'NOT COURSE GROUP' ENROLLMENTTYPE
UNION
Select 3 ID, 23753 Customer_ID, 'Course' ENROLLMENTTYPE
UNION
Select 4 ID, 7 Customer_ID, 'NOT COURSE' ENROLLMENTTYPE
),
CTE_base_data as (
SELECT
C.ID,
replace(replace(replace(replace(C.[Name],',',''),'"',''),':',''),'?','') [Name] ,
replace(replace(C.[Description],',',''),'"','') [Description],
C.[GUID],
C.Businesskey
FROM Course C
JOIN Course_Group CG ON CG.Course_ID = C.ID
JOIN CourseGroup_CustomerEntitlement CG_CE ON CG_CE.COURSEGROUP_ID = CG.COURSEGROUP_ID
JOIN CustomerEntitlement CE_GROUP ON CE_GROUP.ID = CG_CE.CUSTOMERENTITLEMENT_ID
AND CE_GROUP.ENROLLMENTTYPE = 'CourseGroup'
WHERE
CE_GROUP.Customer_ID = 23753
UNION
SELECT
C.ID,
replace(replace(replace(replace([Name],',',''),'"',''),':',''),'?','') [Name] ,
replace(replace([Description],',',''),'"','') [Description],
[GUID],
Businesskey
FROM Course c
JOIN Course_CustomerEntitlement CCE ON CCE.Course_ID = C.ID
JOIN CustomerEntitlement CE_COURSE ON CE_COURSE.ID = CCE.CUSTOMERENTITLEMENT_ID
AND CE_COURSE.ENROLLMENTTYPE = 'COURSE'
WHERE
CE_COURSE.Customer_ID = 23753
--and COURSESTATUS = 'Published'
--and RETIREDTF = 0
--and businesskey in
-- (
-- ...
-- )
),
CTE_max_data as (
Select name, max(ID) ID
from CTE_base_data
group by name
)
Select Data.*
from CTE_base_data Data
JOIN CTE_max_data Filter
ON Data.ID = Filter.ID
AND Data.Name = Filter.Name
order by name, id asc
This yields:
ID Name Description GUID Businesskey
90000 Contracts ARB5
40000 NOT Contracts ARB1
Please advise where my data assumptions fall flat.

How to merge these queries into 1 using subquery

Select * from HotelPerson
Where RoomID IN (select ID from HotelRoom Where BookingID = 36 )
Select * from HotelCancelationPolicy
Where RoomID IN (select ID from HotelRoom Where BookingID = 36 )
How can I merge these both queries into 1 query ?
This will give you all the columns from both tables in one table.
SELECT *
FROM HotelPerson A, HotelCancelationPolicy B
WHERE A.RoomID = B.RoomID
AND A.RoomID IN (SELECT ID FROM HotelRoom WHERE BookingID = 36)
Use UNION to Get Distinct elements or UNION ALL for all rows from both tables
Select * from HotelPerson
Where RoomID IN (select ID from HotelRoom Where BookingID = 36 )
UNION ALL
Select * from HotelCancelationPolicy
Where RoomID IN (select ID from HotelRoom Where BookingID = 36 )
I guess you want to join the two tables:
select *
from HotelPerson hp
inner join HotelCancelationPolicy hcp
on hp.RoomId = hcp.RoomId
where hp.RoomID IN (select ID
from HotelRoom
where BookingID = 36 )

SQL Select Into #Temp

I have a complex SQL query that works. It's like
SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0
It does what I want it to do. But when I wrap it in
SELECT * INTO #Temp FROM ()
I get an incorrect syntax near ')'.
I'm confused. I just want to put the results into a temp table so I can do further work on it. Why doesn't it work?
You're missing an alias for subquery.
SELECT * INTO #MyTempTable
FROM
(
SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0
) AS DT
select * into TBL_name from
( SELECT * FROM Site s
JOIN (
SELECT DISTINCT z.Value FROM Doc z
JOIN (
SELECT x.DocumentID FROM Doc x
JOIN (
SELECT DocumentID, MAX(VERSION) AS VERSION
FROM Doc GROUP BY DocumentID) y ON y.DocumentID = x.DocumentID
WHERE DocumentTypeID = 78 AND MetadataTypeID = 22 AND VALUE > GETDATE() AND y.Version = x.Version
) a ON z.DocumentID = a.DocumentID
WHERE MetadataTypeID = 2
) b ON b.Value = s.SiteID
WHERE SiteID > 0)al

SQL query select record with Max

I have these records below :
CustomerID | Name | Store | Quantity
1 | Elie | HO | 16
1 | Elie | S1 | 4
I would like to filter customers by taking only their max quantity?
I tried it with Max, but the problem I cannot render all the fields with it. If I add main.store in the first line, the second row shows.
Is there any solution?
Select main.CUSTOMER_ID, main.Name
from
(
Select Name = cus.FIRST_NAME + ' ' + cus.LAST_NAME,
Store = cs.NAME
,Transaction_Number = count(ts.TRANSACTION_SUMMARY_ID)
,cus.CUSTOMER_ID
from TRANSACTION_SUMMARY ts
inner join dbo.CUSTOMER cus
on ts.CUSTOMER_ID = cus.CUSTOMER_ID
inner join dbo.CORPORATE_STORE cs
on ts.CORPORATE_STORE_ID = cs.CORPORATE_STORE_ID
Group by cus.CUSTOMER_ID
,cus.FIRST_NAME
,cus.LAST_NAME
,cs.Name
) as main
Group by CUSTOMER_ID
,main.Name
order by main.CUSTOMER_ID
This is a good use of window functions:
with t as (
Select Name = cus.FIRST_NAME + ' ' + cus.LAST_NAME,
Store = cs.NAME,
Transaction_Number = count(ts.TRANSACTION_SUMMARY_ID) , cus.CUSTOMER_ID
from TRANSACTION_SUMMARY ts
inner join dbo.CUSTOMER cus on ts.CUSTOMER_ID = cus.CUSTOMER_ID
inner join dbo.CORPORATE_STORE cs on ts.CORPORATE_STORE_ID = cs.CORPORATE_STORE_ID
Group by cus.CUSTOMER_ID, cus.FIRST_NAME, cus.LAST_NAME, cs.Name
)
select name, store, Transaction_Number, CUSTOMER_ID
from (select t.*,
row_number() over (partition by customer_id order by transaction_number desc) as seqnum
from t
) t
where seqnum = 1;
You can actually dispense with the subquery. However, using window functions with aggregations looks funny at first:
with t as (
Select Name = cus.FIRST_NAME + ' ' + cus.LAST_NAME,
Store = cs.NAME,
Transaction_Number = count(ts.TRANSACTION_SUMMARY_ID) , cus.CUSTOMER_ID,
row_number() over (partition by cus.CUSTOMER_ID
order by count(ts.TRANSACTION_SUMMARY_ID) desc
) as seqnum
from TRANSACTION_SUMMARY ts
inner join dbo.CUSTOMER cus on ts.CUSTOMER_ID = cus.CUSTOMER_ID
inner join dbo.CORPORATE_STORE cs on ts.CORPORATE_STORE_ID = cs.CORPORATE_STORE_ID
Group by cus.CUSTOMER_ID, cus.FIRST_NAME, cus.LAST_NAME, cs.Name
)
select name, store, Transaction_Number, CUSTOMER_ID
from t
where seqnum = 1;
Please try:
select * From tbl a
where a.Quantity=
(select MAX(b.Quantity) from tbl b where a.CustomerID=b.CustomerID)
what you want is
select customer_id, max( quantity )
from main
group by customer_id
then you can use this to join to itself if you want
select *
from main
, (
select customer_id, max( quantity ) qty
from main
group by customer_id
) m
where main.customer_id = m.customer_id
and main.quantity = m.qty
Obviously, name has no business being in this table, but you included it, so I did too...
SELECT x.*
FROM my_table x
JOIN
( SELECT customerid
, name
, MAX(quantity) max_quantity
FROM my_table
GROUP
BY customerid
, name
) y
ON y.customerid = x.customerid
AND y.name = x.name
AND y.max_quantity = x.quantity;