I have a customer table, and then there's a separate transactional table that cross-references the customer table. With one particular column that I would like to present to the consumer as a combined SQL view. This transactional column is referred to as LastEdited.
The view itself is fine, if I run SELECT statements by querying columns like FirstName, LastName, etc. Where I run into issues is when querying the LastEdited column. This column is using a TOP 1 select criteria. For example, if I query LastEdited BETWEEN '1/1/2019 00:00:01' and '6/30/2019 23:59:59'. The results take a long time, since there are obvious performance penalties.
Any suggestions on how best to handle this? I've tried creating the column for this view by invoking a scalar function, like:
(select dbo.fncUser_LastCustomerEditDate(c.CustomerNo)) as LastEdited
This scalar function basically returns the TOP 1 record. I've also tried creating the column by referencing it against an OUTER APPLY, like:
...OUTER APPLY (SELECT top 1 GMTTimestamp from dbo.tbl121_DataLog dl where dl.PrimaryKey = c.Id and dl.DBActionId In (600001, 600002) order by dl.GMTTimeStamp DESC) dl
so that my SELECT list just looks at:
dl.GMTTimeStamp as LastEdited
Neither option provides me the ability to quickly return results by querying the resultant view based on this column.
Any help or suggestions would be appreciated!
Here are the two view constructions I've tried so far:
CREATE VIEW [dbo].[viwUser_Customers_Custom2]
AS
SELECT c.Id, c.Type, c.CustomerNo, sit.Code AS PrimarySiteCode, sit.Name AS PrimarySiteName, emp.Code AS PrimarySalespersonCode,
emp.Name AS PrimarySalespersonName, c.Title, c.FirstName, c.MiddleName, c.LastName, c.NickName, c.Greeting, c.PreviousName,
dbo.fncCustContactMethodText(c.PreferredContactMethod) AS PreferredContactMethod, cad.Address1, cad.Address2, cad.Address3, cad.City, cad.State,
cad.PostCode, cad.Country, cpp.CountryPrefix AS PhoneCountryPrefix, cpp.AreaCode AS PhoneAreaCode, cpp.Number AS PhoneNumber,
cpp.Extension AS PhoneExtension, dbo.fncCustFormattedPhoneNo(cpp.CountryPrefix, cpp.AreaCode, cpp.Number, cpp.Extension)
AS PhoneNumberFormatted, cpf.CountryPrefix AS FaxCountryPrefix, cpf.AreaCode AS FaxAreaCode, cpf.Number AS FaxNumber,
cpf.Extension AS FaxExtension, dbo.fncCustFormattedPhoneNo(cpf.CountryPrefix, cpf.AreaCode, cpf.Number, cpf.Extension) AS FaxNumberFormatted,
cpm.CountryPrefix AS MobileCountryPrefix, cpm.AreaCode AS MobileAreaCode, cpm.Number AS MobileNumber, cpm.Extension AS MobileExtension,
dbo.fncCustFormattedPhoneNo(cpm.CountryPrefix, cpm.AreaCode, cpm.Number, cpm.Extension) AS MobileNumberFormatted, cpe.EmailAddress, c.Sex,
c.UDFList1, c.UDFList2, c.UDFList3, c.UDFList4, c.UDFList5, c.UDFList6, c.UDFList7, c.UDFList8, c.UDFList9, c.UDFList10, c.UDFList11, c.UDFList12,
c.FingerSize1 AS LeftLittleFingerSize, c.FingerSize2 AS LeftRingFingerSize, c.FingerSize3 AS LeftMiddleFingerSize,
c.FingerSize4 AS LeftIndexFingerSize, c.FingerSize5 AS LeftThumbSize, c.FingerSize6 AS RightThumbSize, c.FingerSize7 AS RightIndexFingerSize,
c.FingerSize8 AS RightMiddleFingerSize, c.FingerSize9 AS RightRingFingerSize, c.FingerSize10 AS RightLittleFingerSize, c.LeftWristSize,
c.RightWristSize, c.NeckSize, c.SocSecNumber, c.POSComments, c.SecureComments, c.Status, c.Active, c.Day, c.Month, c.Year, dbo.fncGetDOB(c.Day,
c.Month, c.Year) AS BirthDate, dbo.fncGetAge(c.Day, c.Month, c.Year, c.Age, c.AgeReferenceDate, GETDATE()) AS Age, CAST('' AS varchar(1000))
AS MailingName, CAST('' AS varchar(1000)) AS GreetingName, CAST(0 AS money) AS CustomerSalesTotalForDateRange, CAST(0 AS money)
AS CustomerSalesTotal, CAST('' AS varchar(50)) AS PartnerCustomerNo, CAST('' AS varchar(20)) AS PartnerBirthDate, CAST(0 AS money)
AS PartnerSalesTotalForDateRange, CAST(0 AS money) AS PartnerSalesTotal, dbo.fnc604S_GetAnniversary(c.Id) as Anniversary,
Coalesce((Select Top 1 cd.DiscountPercent From tbl605_CustDiscount cd Where cd.CustomerId = c.Id),0) as DiscountPercent,
dl.GMTTimeStamp as LastEdited
FROM dbo.tbl600_Customer AS c INNER JOIN
dbo.tbl103_Sites AS sit ON c.SiteId = sit.Id LEFT OUTER JOIN
dbo.tbl601_CustAddress AS cad ON cad.CustomerId = c.Id AND cad.[Default] = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpp ON cpp.CustomerId = c.Id AND cpp.Device = 1 AND cpp.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpf ON cpf.CustomerId = c.Id AND cpf.Device = 3 AND cpf.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpm ON cpm.CustomerId = c.Id AND cpm.Device = 2 AND cpm.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpe ON cpe.CustomerId = c.Id AND cpe.Device = 4 AND cpe.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl405_Employees AS emp ON dbo.fnc600S_GetPrimarySalespersonId(c.Id) = emp.Id OUTER APPLY
(SELECT top 1 GMTTimestamp from dbo.tbl121_DataLog dl where dl.PrimaryKey = c.Id and dl.DBActionId In (600001, 600002) order by dl.GMTTimeStamp DESC) dl
GO
CREATE VIEW [dbo].[viwUser_Customers_Custom]
AS
SELECT c.Id, c.Type, c.CustomerNo, sit.Code AS PrimarySiteCode, sit.Name AS PrimarySiteName, emp.Code AS PrimarySalespersonCode,
emp.Name AS PrimarySalespersonName, c.Title, c.FirstName, c.MiddleName, c.LastName, c.NickName, c.Greeting, c.PreviousName,
dbo.fncCustContactMethodText(c.PreferredContactMethod) AS PreferredContactMethod, cad.Address1, cad.Address2, cad.Address3, cad.City, cad.State,
cad.PostCode, cad.Country, cpp.CountryPrefix AS PhoneCountryPrefix, cpp.AreaCode AS PhoneAreaCode, cpp.Number AS PhoneNumber,
cpp.Extension AS PhoneExtension, dbo.fncCustFormattedPhoneNo(cpp.CountryPrefix, cpp.AreaCode, cpp.Number, cpp.Extension)
AS PhoneNumberFormatted, cpf.CountryPrefix AS FaxCountryPrefix, cpf.AreaCode AS FaxAreaCode, cpf.Number AS FaxNumber,
cpf.Extension AS FaxExtension, dbo.fncCustFormattedPhoneNo(cpf.CountryPrefix, cpf.AreaCode, cpf.Number, cpf.Extension) AS FaxNumberFormatted,
cpm.CountryPrefix AS MobileCountryPrefix, cpm.AreaCode AS MobileAreaCode, cpm.Number AS MobileNumber, cpm.Extension AS MobileExtension,
dbo.fncCustFormattedPhoneNo(cpm.CountryPrefix, cpm.AreaCode, cpm.Number, cpm.Extension) AS MobileNumberFormatted, cpe.EmailAddress, c.Sex,
c.UDFList1, c.UDFList2, c.UDFList3, c.UDFList4, c.UDFList5, c.UDFList6, c.UDFList7, c.UDFList8, c.UDFList9, c.UDFList10, c.UDFList11, c.UDFList12,
c.FingerSize1 AS LeftLittleFingerSize, c.FingerSize2 AS LeftRingFingerSize, c.FingerSize3 AS LeftMiddleFingerSize,
c.FingerSize4 AS LeftIndexFingerSize, c.FingerSize5 AS LeftThumbSize, c.FingerSize6 AS RightThumbSize, c.FingerSize7 AS RightIndexFingerSize,
c.FingerSize8 AS RightMiddleFingerSize, c.FingerSize9 AS RightRingFingerSize, c.FingerSize10 AS RightLittleFingerSize, c.LeftWristSize,
c.RightWristSize, c.NeckSize, c.SocSecNumber, c.POSComments, c.SecureComments, c.Status, c.Active, c.Day, c.Month, c.Year, dbo.fncGetDOB(c.Day,
c.Month, c.Year) AS BirthDate, dbo.fncGetAge(c.Day, c.Month, c.Year, c.Age, c.AgeReferenceDate, GETDATE()) AS Age, CAST('' AS varchar(1000))
AS MailingName, CAST('' AS varchar(1000)) AS GreetingName, CAST(0 AS money) AS CustomerSalesTotalForDateRange, CAST(0 AS money)
AS CustomerSalesTotal, CAST('' AS varchar(50)) AS PartnerCustomerNo, CAST('' AS varchar(20)) AS PartnerBirthDate, CAST(0 AS money)
AS PartnerSalesTotalForDateRange, CAST(0 AS money) AS PartnerSalesTotal, dbo.fnc604S_GetAnniversary(c.Id) as Anniversary,
Coalesce((Select Top 1 cd.DiscountPercent From tbl605_CustDiscount cd Where cd.CustomerId = c.Id),0) as DiscountPercent, (select dbo.fncUser_LastCustomerEditDate(c.CustomerNo)) as LastEdited
FROM dbo.tbl600_Customer AS c INNER JOIN
dbo.tbl103_Sites AS sit ON c.SiteId = sit.Id LEFT OUTER JOIN
dbo.tbl601_CustAddress AS cad ON cad.CustomerId = c.Id AND cad.[Default] = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpp ON cpp.CustomerId = c.Id AND cpp.Device = 1 AND cpp.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpf ON cpf.CustomerId = c.Id AND cpf.Device = 3 AND cpf.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpm ON cpm.CustomerId = c.Id AND cpm.Device = 2 AND cpm.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl602_CustPhone AS cpe ON cpe.CustomerId = c.Id AND cpe.Device = 4 AND cpe.DeviceDefault = 1 LEFT OUTER JOIN
dbo.tbl405_Employees AS emp ON dbo.fnc600S_GetPrimarySalespersonId(c.Id) = emp.Id
GO
Time lags of 1-2 minutes querying the SQL view.
I found an easier way to accomplish this. Will just add a SQL trigger to insert a timestamped row into a supplementary table. This table will have the proper construction to make for quicker lookups.
I have a query from an old database that we converting into T-SQL, but having issues using CTE:
Original Query in Oracle:
select company_name, display_name, active_flag, naic_code, group_number, alien_code, fein,
status_desc, status_detail_desc, due_to_merger_flag, co_code, to_char(status_date, 'MM/DD/YYYY')
Inactive_Date, active_flag from
(select nm.COMPANY_NAME, cmp.recordid_number, orgtp.display_name, cmp.active_flag,
cmp.naic_code, grpnm.group_number, cmp.alien_code, cmp.fein, st.status_desc, stdt.status_detail_desc,
storgjn.due_to_merger_flag, storgjn.co_code, storgjn.status_date, st.active_flag as activestatus,
max(storgjn.status_date) over (partition by cmp.recordid_number, orgtp.display_name) max_status_date
from aip.co_company cmp join aip.CO_NAME nm on cmp.COMPANY_ID = nm.company_id and nm.active_flag = 1
left outer join aip.co_company_group_jn cmpgrpjn on nm.COMPANY_ID = cmpgrpjn.company_id and cmpgrpjn.active_flag = 1
left outer join aip.co_group_name grpnm on cmpgrpjn.group_id = grpnm.group_id and grpnm.active_flag = 1
join aip.co_org org on cmp.COMPANY_ID = org.company_id
join aip.co_org_type orgtp on org.org_type_id = orgtp.org_type_id
join aip.co_status_org_jn storgjn on org.org_id = storgjn.org_id
join aip.co_status_detail stdt on storgjn.status_detail_id = stdt.status_detail_id
join aip.co_status st on stdt.status_id = st.status_id
WHERE cmp.recordid_number = '10632' AND
stdt.status_detail_desc <> 'Record Begin Date')
WHERE status_date = max_status_date
And converting into T-SQl im using:
WITH YOURCTE(WHATEVA) AS
(
SELECT nm.COMPANY_NAME, cmp.recordid_number, orgtp.display_name, cmp.active_flag,
cmp.naic_code, grpnm.group_number, cmp.alien_code, cmp.fein, st.status_desc, stdt.status_detail_desc,
storgjn.due_to_merger_flag, storgjn.co_code, storgjn.status_date, st.active_flag as activestatus,
max(storgjn.status_date) over (partition by cmp.recordid_number, orgtp.display_name) max_status_date
from aip.co_company cmp join aip.CO_NAME nm on cmp.COMPANY_ID = nm.company_id and nm.active_flag = 1
left outer join aip.co_company_group_jn cmpgrpjn on nm.COMPANY_ID = cmpgrpjn.company_id and cmpgrpjn.active_flag = 1
left outer join aip.co_group_name grpnm on cmpgrpjn.group_id = grpnm.group_id and grpnm.active_flag = 1
join aip.co_org org on cmp.COMPANY_ID = org.company_id
join aip.co_org_type orgtp on org.org_type_id = orgtp.org_type_id
join aip.co_status_org_jn storgjn on org.org_id = storgjn.org_id
join aip.co_status_detail stdt on storgjn.status_detail_id = stdt.status_detail_id
join aip.co_status st on stdt.status_id = st.status_id
WHERE cmp.recordid_number = '10632' AND
stdt.status_detail_desc <> 'Record Begin Date'
)
select company_name, display_name, active_flag, naic_code, group_number, alien_code, fein,
status_desc, status_detail_desc, due_to_merger_flag, co_code, CONVERT(VARCHAR(10),status_date,120) AS Inactive_Date,
active_flag
FROM YOURCTE
WHERE status_date = max_status_date
But I get the following error :
Msg 8158, Level 16, State 1, Line 2
'YOURCTE' has more columns than were specified in the column list.
The reason i have more columns in my cte is because I'm using the recordid_number column to bring other data for where conditioning. I will appreciate some help, thank you.
Either replace "WHATEVA" with a complete list of the column aliases you want to use, or remove it and let the original column names stand.
Inherit
;WITH YOURCTE AS
(...
Explicit
;WITH YOURCTE (COMPANY_NAME, recordid_number, ...) AS
(...
I want max dated rows for per GroupCode
I wrote this.
SELECT FH.BelgeNo AS FaturaNo
,FHD.UrunId
,FH.Tarih
,UG.Grup AS GrupKodu
,FHD.Kodu
,FHD.UrunAdi
,FHD.BirimFiyat
FROM FirmaHareketDetayi FHD
LEFT JOIN FirmaHareketleri FH ON FH.ID = FHD.HareketId
LEFT JOIN Urunler U ON U.UrunId = FHD.UrunId --and U.Kodu = FHD.Kodu
LEFT JOIN UrunGruplari UG ON UG.GrupId = U.GrupId
WHERE FHD.Kodu = '2S619H307CF'
AND FH.FirmaId = 2610
ORDER BY Tarih DESC
and results are like this
There are 2 PIERBURG rows.
is it possible to get only one PIERBURG ?
I mean max dated one (Tarih: Date column, GrupKodu: Group Code)
Notes: Table UrunGrupları: ProductGroups
Table FirmaHareketleri: FirmMovements
Table FirmaHareketDetayi: FirmMovementDetails (Connected with FirmMovements by HareketId (Foreign Key))
Sorry about my english :(
You can use window functions for this
;with cte as (
SELECT FH.BelgeNo AS FaturaNo
,FHD.UrunId
,FH.Tarih
,UG.Grup AS GrupKodu
,FHD.Kodu
,FHD.UrunAdi
,FHD.BirimFiyat
, row_number() over(partition by UG.Grup order by FH.Tarih desc) as rownum
FROM FirmaHareketDetayi FHD
LEFT JOIN FirmaHareketleri FH ON FH.ID = FHD.HareketId
LEFT JOIN Urunler U ON U.UrunId = FHD.UrunId --and U.Kodu = FHD.Kodu
LEFT JOIN UrunGruplari UG ON UG.GrupId = U.GrupId
WHERE FHD.Kodu = '2S619H307CF'
AND FH.FirmaId = 2610
)
select *
from cte
where rownum = 1
I need to retrieve the latest loadid by location now with multiple joins.
for example ibiza's latest loadid is 692 and there are 2 records. The query below retrieves all of the loadid's for that location and not just the max. how can i achieve bringing back the latest records by location with the max(loadid) from the query below:
select
MAX(t.loadid) AS loadid,
a.process_id,
p.partitionkey,
-- t.partitionkey,
p.partdesc,
p.partname,
c.catname,
r.rule_name,
r.file_path,
a.execution_start_time,
a.execution_end_time,
a.records_processed
-- a.status,
-- a.last_updated_by as processed_by,
-- a.last_update_date
FROM
data t
INNER JOIN part p
ON t.partitionkey = p.partitionkey
INNER JOIN process a
ON t.loadid = a.process_id
INNER JOIN categ c
ON t.catkey = c.catkey
INNER JOIN balance r
ON t.RULE_ID = r.RULE_ID
WHERE
p.partname = 'ibiza'
GROUP BY
t.loadid,
a.process_id,
p.partitionkey,
t.partitionkey,
p.partdesc,
p.partname,
c.catname,
r.rule_name,
r.file_path,
a.execution_start_time,
a.execution_end_time,
a.records_processed;
You can use CTE :
;WITH MaxLoadId AS
(
select MAX(t.loadid) AS loadid, p.partitionkey, p.partdesc, p.partname
FROM data t
INNER JOIN part p ON t.partitionkey = p.partitionkey
WHERE p.partname = 'ibiza'
GROUP BY p.partitionkey, p.partdesc, p.partname
)
select
mli.loadid AS loadid,
a.process_id,
mli.partitionkey,
-- t.partitionkey,
mli.partdesc,
mli.partname,
c.catname,
r.rule_name,
r.file_path,
a.execution_start_time,
a.execution_end_time,
a.records_processed
-- a.status,
-- a.last_updated_by as processed_by,
-- a.last_update_date
FROM MaxLoadId mli
INNER JOIN data t ON mli.loadid = t.loadid
INNER JOIN process a ON mli.loadid = a.process_id
INNER JOIN categ c ON t.catkey = c.catkey
INNER JOIN balance r ON t.RULE_ID = r.RULE_ID