I've been trying to assemble a stored procedure on my Azure database that when it runs the query, it returns one output value from one specific column.
The likelihood of multiple results is zero since the the table being queried has 3 columns, and the query must mach 2. Then it grabs data from another table. The key is I need the first query to output the value in order to commence the second query.
At present I have 2 procedures, I would like to have one.
Query is as such for the moment:
select
customers_catalogs_define.catalog_id
from
customers_catalogs
left outer join
customers_catalogs_define on customers_catalogs.catalog_id = customers_catalogs_define.catalog_id
where
customers_catalogs.catalog_unique_identifier = #catalog_unique
AND customers_catalogs_define.customer_id = #customer_id
The output of course is the catalog_id. From that I take it into another query which I have that does the actual list retrieval. At the very least I would like to add a line that simply states #catalog_id = output
Thanks
You have two options basically to have this work :
Since I haven't seen your second query, just make sure its querying the correct table listed below as CUSTOMERS_CATALOGS_DEFINE
Using a variable as you suggested:
DECLARE #CATALOG_ID INT
SET #CATALOG_ID = (
SELECT CUSTOMERS_CATALOGS_DEFINE.CATALOG_ID
FROM CUSTOMERS_CATALOGS
LEFT OUTER JOIN CUSTOMERS_CATALOGS_DEFINE
ON CUSTOMERS_CATALOGS.CATALOG_ID = CUSTOMERS_CATALOGS_DEFINE.CATALOG_ID
WHERE CUSTOMERS_CATALOGS.CATALOG_UNIQUE_IDENTIFIER = #CATALOG_UNIQUE
AND CUSTOMERS_CATALOGS_DEFINE.CUSTOMER_ID = #CUSTOMER_ID )
SELECT *
FROM CUSTOMERS_CATALOGS_DEFINE
WHERE CATALOG_ID = #CATALOG_ID
Second option would be to do it in one query:
SELECT *
FROM CUSTOMERS_CATALOGS_DEFINE
WHERE CATALOG_ID IN (
SELECT CUSTOMERS_CATALOGS_DEFINE.CATALOG_ID
FROM CUSTOMERS_CATALOGS
LEFT OUTER JOIN CUSTOMERS_CATALOGS_DEFINE
ON CUSTOMERS_CATALOGS.CATALOG_ID = CUSTOMERS_CATALOGS_DEFINE.CATALOG_ID
WHERE CUSTOMERS_CATALOGS.CATALOG_UNIQUE_IDENTIFIER = #CATALOG_UNIQUE
AND CUSTOMERS_CATALOGS_DEFINE.CUSTOMER_ID = #CUSTOMER_ID
)
Related
I have a legacy DB. A stored procedure SC_Total_Alerts_SP runs and fetches data every week. This has been going on for years. Now the requirements are such that I need to get a few extra columns. These columns are not part of the legacy DB. I know the changes that I need to do to the stored procedure, but my question is that how can I make sure that I do not lose any legacy data.
Query:
DECLARE #my_Date DATETIME = GETDATE()
SELECT
#my_Date AS Date,
Title_9691DD10_7211_C835_E3E7_6B38AF8B8104 AS Alert,
Priority_B930B964_A1C4_0B5A_B2D1_BFBE9ECDC794 AS Priority,
SDUA.DisplayName AS Name
FROM
[ServiceManager].[dbo].[MT_System$WorkItem$Incident] WII
LEFT OUTER JOIN
(SELECT *
FROM [ServiceManager].[dbo].Relationship
WHERE RelatiONshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722') ATU ON ATU.SourceEntityId = WII.BaseManagedEntityId
LEFT OUTER JOIN
[ServiceManager].[dbo].MT_System$Domain$User SDUA ON SDUA.BaseManagedEntityId = ATU.TargetEntityId
INNER JOIN
(SELECT *
FROM [ServiceManager].[dbo].LocalizedText
WHERE ElementName LIKE '%IncidentSTATUSEnum%'
AND LanguageCode = 'ENU'
AND DisplayStringId IS NOT NULL) LTS ON LTS.LTStringId = WII.Status_785407A9_729D_3A74_A383_575DB0CD50ED
WHERE
LTS.ElementName LIKE '%Resolved'
AND SDUA.DisplayName IS NOT NULL
AND CreatedDate_6258638D_B885_AB3C_E316_D00782B8F688 > DateAdd(dd, -7, #my_Date)
The easy way is to put the original query in a WITH statement, then use that derived table and left outer join the new data to it to get the new columns.
I have an update query where I am trying to find the net interest from multiple accounts on three different transaction tables deposits, checks, and general entries. The problem I'm running into is when one of those tables has no entries for a loan number to an interest account the select returns nothing and subsequently displays a null in the production table too. Negating the other tables if they return rows from interest account. If all three tables have a row for interest the query works fine.
Here's the code:
UPDATE Prod
SET Prod.InterestSpread = (T1.Amount+T2.Amount-T3.Amount)
FROM dbo.Production_Pipeline as Prod
LEFT JOIN
(
SELECT LoanNumber,COALESCE(SUM(JournalLineAmount),0)as Amount
FROM dbo.GeneralLedger
WHERE (JournalLineAccountRefListID = 'BB0000-1103842703'
OR JournalLineAccountRefListID = '800001DA-1202763722')
) AS T1
ON T1.LoanNumber = Prod.LoanNumber
LEFT JOIN
(
SELECT LoanNumber,COALESCE(SUM(DepositLineAmount),0)as Amount
FROM dbo.DepositLedger
WHERE ( DepositLineAccountRefListID = 'BB0000-1103842703'
OR DepositLineAccountRefListID = '800001DA-1202763722')
) AS T2
ON T2.LoanNumber = Prod.LoanNumber
LEFT JOIN
(
SELECT LoanNumber,COALESCE(SUM(ExpenseLineAmount),0) AS Amount
FROM dbo.CheckLedger
WHERE(ExpenseLineAccountRefListID = '800002B4-1308771936'
OR ExpenseLineAccountRefListID = 'D30000-1105022008'
OR ExpenseLineAccountRefListID = '8000029E-1283179936'
OR ExpenseLineAccountRefListID = 'BB0000-1103842703'
OR ExpenseLineAccountRefListID = '800001DA-1202763722')
) AS T3
ON T3.LoanNumber = Prod.LoanNumber
So an inccorect result update looks like
T1Amount: 496.08
T2Amount:
T3Amount: 373.92
Interest Spread: NULL
I've done some quite a bit of research on this site but, have been unable to apply your wisdom to my specific issue so any help here would greatly be appreciated.
Move your COALESCE statement to outside of the JOIN and remove it from the subqueries:
UPDATE Prod
SET Prod.InterestSpread =
COALESCE(T1.Amount,0)+COALESCE(T2.Amount,0)-COALESCE(T3.Amount,0)
...
The problem is your subqueries return no results, thus coalesce inside of that cannot be applied to the field. By using it outside of the outer join, you ensure if the result is null, it converts properly.
How can I add the results from a query by parameter to another table using a stored procedure?
Here is my select query text:
SELECT
dbo.PortfolioH.Epic,
dbo.PortfolioH.AlertRatings,
dbo.UserAccounts.Email,
dbo.PortfolioH.UserN
FROM
dbo.PortfolioH
LEFT OUTER JOIN
dbo.UserAccounts ON dbo.PortfolioH.UserN = dbo.UserAccounts.UserN
GROUP BY
dbo.PortfolioH.Epic,
dbo.PortfolioH.AlertRatings,
dbo.UserAccounts.Email,
dbo.PortfolioH.UserN
HAVING
(dbo.PortfolioH.AlertRatings = N'yes')
I want to append to table AlertEmails where dbo.PortfolioH.Epic = #Epic
any help greatly appreciated.
Just use the standard INSERT.....SELECT construct, which takes the data to be inserted from a query, something like this:
INSERT INTO dbo.AlertsEmails (Epic, AlertRatings, Email, UserN, AlertType)
SELECT dbo.PortfolioH.Epic, dbo.PortfolioH.AlertRatings,
dbo.UserAccounts.Email, dbo.PortfolioH.UserN, 1 As AlertType
FROM dbo.PortfolioH LEFT OUTER JOIN
dbo.UserAccounts ON dbo.PortfolioH.UserN = dbo.UserAccounts.UserN
GROUP BY dbo.PortfolioH.Epic, dbo.PortfolioH.AlertRatings, dbo.UserAccounts.Email,
dbo.PortfolioH.UserN
HAVING (dbo.PortfolioH.AlertRatings = N'yes') ;
It just runs the query, but instead of returning a result set, inserts the resulting rows into the table. Note that I've added the AlertType column in the INSERT part and added a fixed value in the SELECT part, as they must match exactly.
I am trying to find subdepartments where they link by description if one is their it should return the id of the one in the table I am using the following query.
SELECT DISTINCT Subdeptcode
,SubDepartment
FROM SkechersPricat
WHERE SubDepartment IN ( SELECT DISTINCT description
FROM SubDept )
AND processed = false
AND SubDeptCode = 0
I need To be able to return the subdeptcode from the sub dept table if one exists if one Doesnt exist create it so I need a query that can account for both condision im using vb.net
Main File looks like the following
Sub Debt table above
For starters lets look at your query
SELECT DISTINCT Subdeptcode
,SubDepartment
FROM SkechersPricat
WHERE SubDepartment IN ( SELECT DISTINCT description
FROM SubDept )
AND processed = false
AND SubDeptCode = 0
you are trying to say that SubDepartment column needs to be in one of the values of description from SubDept table. Unless your SubDepartment matches description exactly it will not return anything.
Proper syntax for your query would be using LEFT OUTER JOIN. By using LEFT OUTER JOIN you are saying to get all results from your left table and only records that match in your right table. Thus you still get all the records from main table even if there is no match in SubDept table.
Your query will be like this
SELECT DISTINCT s.Subdeptcode
,s.SubDepartment
FROM SkechersPricat s
LEFT OUTER JOIN SubDept sd
ON s.SubDepartment = sd.description
WHERE s.processed = false
AND s.SubDeptCode = 0
What I do see in your screenshot that GeminDepartmentID corresponds to DeptCode from SubDept table. I think you are not joining on correct value.
I have a SQL 2005 table consisting of around 10million records (dbo.Logs).
I have another table, dbo.Rollup that matches distinct dbo.Logs.URL to a FileId column in a third table, dbo.Files. The dbo.Rollup table forms the basis of various aggregate reports we run at a later stage.
Suffice to say for now, the problem I am having is in populating dbo.Rollup efficiently.
By definition, dbo.Logs has potentially tens of thousands of rows which all share the same URL field value. In our application, one URL can be matched to one dbo.Files.FileId. I.E. There is a many-to-one relationship between dbo.Logs.URL and dbo.Files.FileId (we parse the values of dbo.Logs to determine what the appropriate FileId is for a given URL).
My goal is to significantly reduce the amount of time it takes the first of three stored procedures that run in order to create meaningful statistics from our raw log data.
What I need is a specific example of how to refactor this SQL query to be much more efficient:
sp-Rollup-Step1:
INSERT INTO dbo.Rollup ([FileURL], [FileId])
SELECT
logs.RequestedFile As [URL],
FileId = dbo.fn_GetFileIdFromURL(l.RequestedFile, l.CleanFileName)
FROM
dbo.Logs l (readuncommitted)
WHERE
NOT EXISTS (
SELECT
FileURL
FROM
dbo.Rollup
WHERE
FileUrl = RequestedFile
)
fn_GetFileIdFromURL():
CREATE FUNCTION [dbo].[fn_GetFileIdFromURL]
(
#URL nvarchar(500),
#CleanFileName nvarchar(255)
)
RETURNS uniqueidentifier
AS
BEGIN
DECLARE #id uniqueidentifier
if (exists(select FileURL from dbo.[Rollup] where [FileUrl] = #URL))
begin
-- This URL has been seen before in dbo.Rollup.
-- Retrieve the FileId from the dbo.Rollup table.
set #id = (select top 1 FileId from dbo.[Rollup] where [FileUrl] = #URL)
end
else
begin
-- This is a new URL. Hunt for a matching URL in our list of files,
-- and return a FileId if a match is found.
Set #id = (
SELECT TOP 1
f.FileId
FROM
dbo.[Files] f
INNER JOIN
dbo.[Servers] s on s.[ServerId] = f.[ServerId]
INNER JOIN
dbo.[URLs] u on
u.[ServerId] = f.[ServerId]
WHERE
Left(u.[PrependURLProtocol],4) = left(#URL, 4)
AND #CleanFileName = f.FileName
)
end
return #id
END
Key considerations:
dbo.Rollup should contain only one entry for each DISTINCT/unique URL found in dbo.tLogs.
I would like to omit records from being inserted into dbo.[Rollup] where the FileId is NULL.
In my own observations, it seems the slowest part of the query by far is in the stored procedure: the "NOT EXISTS" clause (I am not sure at this point whether that continually refreshes the table or not).
I'm looking for a specific solution (with examples using either pseudo-code or by modifying my procedures shown here) - answer will be awarded to those who provide it!
Thanks in advance for any assistance you can provide.
/Richard.
Short answer is you have a CURSOR here. The scalar UDF is run per row of output.
The udf could be 2 LEFT JOINs onto derived tables. A rough outline:
...
COALESCE (F.xxx, L.xxx) --etc
...
FROM
dbo.Logs l (readuncommitted)
LEFT JOIN
(select DISTINCT --added after comment
FileId, FileUrl from dbo.[Rollup]) R ON L.FileUrl = R.FileUrl
LEFT JOIN
(SELECT DISTINCT --added after comment
f.FileId,
FileName ,
left(#PrependURLProtocol, 4) + '%' AS Left4
FROM
dbo.[Files] f
INNER JOIN
dbo.[Servers] s on s.[ServerId] = f.[ServerId]
INNER JOIN
dbo.[URLs] u on
u.[ServerId] = f.[ServerId]
) F ON L.CleanFileName = R.FileName AND L.FileURL LIKE F.Left4
...
I'm also not sure if you need the NOT EXISTS because of how the udf works. If you do, make sure the columns are indexed.
I think your hotspot is located here:
Left(u.[PrependURLProtocol],4) = left(#URL, 4)
This will cause the server to do a scan on the url table. You should not use a function on a field in a join clause. try to rewrite that to something like
... where PrependURLProtocol like left(#URL, 4) +"%"
And make sure you have an index on the field.
INSERT INTO dbo.Rollup ([FileURL], [FileId])
SELECT
logs.RequestedFile As [URL],
FileId = dbo.fn_GetFileIdFromURL(l.RequestedFile, l.CleanFileName)
FROM dbo.Logs l (readuncommitted) LEFT OUTER JOIN dbo.Rollup
on FileUrl = RequestedFile
WHERE FileUrl IS NULL
The logic here is that if dbo.Rollup does not exist for the given FileUrl, then the left outer join will turn up null. The NOT EXISTS now becomes an IS NULL, which is faster.