I am trying to create a stored procedure whereupon I input a (simple for now) query into a temp table, and then replace some of the data with data from a different table based on a key.
Here is the complete code:
CREATE PROCEDURE GetInquiryList
AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#Inq ') IS NOT NULL
DROP TABLE #Inq
SELECT i.*,q.QuoteID INTO #Inq FROM Inquiries i left join Quotes q on i.InquiryId = q.InquiryId
WHERE i.YNDeleted = 0
--SELECT * FROM #Inq
UPDATE #Inq
SET j.InquiryCustomerName = c.CustomerName,
j.InquiryCustomerEmail = c.CustomerEmail,
j.InquiryCustomerPhone = c.CustomerPhone1,
j.InquiryBestTimetoCall = c.CustomerBestTimetoCall,
j.InquiryDay = c.customerDay,
j.InquiryNight = c.CustomerNight
SELECT c.CustomerName,
c.CustomerEmail,
c.CustomerPhone1,
c.CustomerBestTimetoCall,
c.customerDay,
c.CustomerNight
FROM Customers c
INNER JOIN #Inq j ON
j.InquiryCustomerID = c.CustomerID
SELECT * FROM #Inq
END
I get the following error:
Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound
I get this error for whatever column is placed first after the SET command.
Both query pieces of this work independently (the first select creating the temp table and the joined query at the bottom). The data returned is correct. I have tried using aliases (SELECT c.CustomerName AS Name, ...).
Originally, I used "#Inq i" in the second command, but changed to "j" out of an abundance of caution.
I have also run the command against the original table (substituting the Inquiry table for the temp table #Inq, and that fails as well).
Shortening it to this:
UPDATE #Inq
SET j.InquiryCustomerName = c.CustomerName,
j.InquiryCustomerEmail = c.CustomerEmail,
j.InquiryCustomerPhone = c.CustomerPhone1,
j.InquiryBestTimetoCall = c.CustomerBestTimetoCall,
j.InquiryDay = c.customerDay,
j.InquiryNight = c.CustomerNight
FROM Customers c
INNER JOIN #Inq j ON
j.InquiryCustomerID = c.CustomerID
I get a different error:
Msg 4104, Level 16, State 1, Line 15 The multi-part identifier "j.InquiryCustomerName" could not be bound
I'm sure it's probably something simple,(so simple that I can't find any references in any of my searches).
I'm sure it has something to do with the fact that you can't update the same instance of the table used in the join (I'm going to have to re-join again with a "k" alias). How do I do this?
data from the first query
data from the first query
data from the second select statement on the actual temp table
Here is what I updated the stored procedure to, which works exactly how I need it to:
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#Inq ') IS NOT NULL
DROP TABLE #Inq
SELECT i.* INTO #Inq FROM (
select inquiries.InquiryId,
inquiries.InquiryDateReceived,
inquiries.InquiryCustomerID,
cust.CustomerName as InquiryCustomerName,
cust.CustomerEmail as InquiryCustomerEmail,
cust.CustomerPhone1 as InquiryCustomerPhone,
cust.CustomerBestTimeToCall as InquiryBestTimeToCall,
cust.CustomerDay as InquiryDay,
cust.CustomerNight as InquiryNight,
inquiries.InquiryServiceType,
inquiries.InquiryServiceID,
inquiries.InquiryTimeframe,
inquiries.InquiryProjectDescription,
inquiries.InquiryDateResponded,
inquiries.InquiryCustomerReply,
inquiries.YNMigrated,
inquiries.InquiryDateClosed,
inquiries.YNClosed,
inquiries.YNDeleted
from inquiries inner join dbo.Customers as cust
on inquiries.InquiryCustomerID = cust.CustomerID and inquiries.InquiryCustomerID > 0
UNION ALL
select inquiries.InquiryId,
inquiries.InquiryDateReceived,
inquiries.InquiryCustomerID,
InquiryCustomerName,
InquiryCustomerEmail,
InquiryCustomerPhone,
InquiryBestTimeToCall,
InquiryDay,
InquiryNight,
inquiries.InquiryServiceType,
inquiries.InquiryServiceID,
inquiries.InquiryTimeframe,
inquiries.InquiryProjectDescription,
inquiries.InquiryDateResponded,
inquiries.InquiryCustomerReply,
inquiries.YNMigrated,
inquiries.InquiryDateClosed,
inquiries.YNClosed,
inquiries.YNDeleted
from inquiries WHERE inquiries.InquiryCustomerID = 0
) i
select i.*, q.QuoteID
FROM #Inq i left join dbo.Quotes as q
on i.InquiryId = q.InquiryId
WHERE i.YNDeleted = 0
END
Just stop using this pattern without a really good reason. Here it only appears to create more work for the database engine with no obvious benefit. Your procedure - as posted - has trivially simple queries so why bother with the temp table and the update?
It is also time to start learning and using best practices. Terminate EVERY statement - eventually it will be required. Does order of the rows in your resultset matter? Usually it does and that is only guaranteed when that resultset is produced by a query that includes an ORDER BY clause.
As a developing/debugging short cut, you can harness the power of CTEs to help you build a working query. In this case, you can "stuff" your first query into a CTE and then simply join the CTE to Customers and "adjust" the columns you need in that resultset.
WITH inquiries as (
select inq.*, qt.QuoteID
FROM dbo.Inquiries as inq left join dbo.Quotes as qt
on inq.InquiryId = qt.InquiryId
WHERE inq.YNDeleted = 0
)
select inquiries.<col>,
...,
cust.CustomerName as "InquiryCustomerName",
...
from inquiries inner (? guessing) dbo.Customers as cust
on inquiries.InquiryCustomerID = cust.CustomerID
order by ...
;
Schema names added as best practice. Listing the columns you actually need in your resultset is another best practice. Note I did not do that for the query in the CTE but you should. You can choose to create aliases for your resultset columns as needed. I listed one example that corresponds to your UPDATE attempt.
It is odd and very suspicious that all of the columns you intended to UPDATE exist in the Inquiries table. Are you certain you need to do that at all? Do they actually differ from the related columns in the Customer table? Also odd that the value 0 exists in InquiryCustomerID - suggesting you might have not a FK to enforce the relationship. Perhaps that means you need to outer join rather than inner join (as I wrote). If an outer join is needed, then you will need to use CASE expressions to "choose" which value (the CTE value or the Customer value) to use for those columns.
After learning a lot more about how things get bound to models, and how to further use sql, here is what my stored procedure looks like:
ALTER PROCEDURE [dbo].[GetInquiryList]
#InquiryID int = 0
AS
BEGIN
SET NOCOUNT ON
select i.InquiryId,
i.InquiryDateReceived,
i.InquiryCustomerID,
InquiryCustomerName =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryCustomerName
ELSE c.CustomerName
END,
InquiryCustomerEmail =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryCustomerEmail
ELSE c.CustomerEmail
END,
InquiryCustomerPhone =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryCustomerPhone
ELSE c.CustomerPhone1
END,
InquiryBestTimetoCall =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryBestTimetoCall
ELSE c.CustomerBestTimetoCall
END,
InquiryDay =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryDay
ELSE c.CustomerDay
END,
InquiryNight =
CASE i.InquiryCustomerID
WHEN 0 THEN i.InquiryNight
ELSE c.CustomerNight
END,
i.InquiryServiceType,
i.InquiryServiceID,
i.InquiryTimeframe,
i.InquiryProjectDescription,
i.InquiryDateResponded,
i.InquiryCustomerReply,
i.YNMigrated,
i.InquiryDateClosed,
i.YNClosed,
i.YNDeleted, ISNULL(q.QuoteId,0) AS Quoteid
FROM dbo.Inquiries i
LEFT JOIN dbo.Quotes q ON i.InquiryId = q.InquiryId
LEFT JOIN dbo.Customers c ON i.InquiryCustomerID = c.CustomerId
WHERE i.YNDeleted = 0
END
I'm sure there are additional enhancements that could be made, but avoiding the union is a big savings. Thanks, everyone.
I am trying to gather the information on which store is receiving which SKU along with some other relevant info. The data is in multiple tables so i am trying innerjoin the info. I am using SAS and it runs in SQL Server via passthrough. Below is the query i tried. I have confirmed that || works in the pass through. The issue seems to start in the from statement
connect to odbc (dsn='X' uid='X' pwd='XY');
create table School.TRANS_INFO as SELECT * from connection to odbc
(SELECT Distinct
S.Schd_t AS Schd_Date format MMDDYY10.,
S.otb As Ship_Loc,
W.store_NUMBER AS store,
S.SHP_ID AS SHIP_ID,
W.store_CITY_STATE,
Q.Stat_CD AS Status,
(S.PROD_CD || S.plt_CD) AS SKU,
W.ACCOUNT_TYPE as Location
FROM
SHPMT_DTL S
INNER JOIN store W ON W.store_NUMBER = S.Otb_DEST_store_NBR,
INNER JOIN SHP_LEG Q ON Q.SHPMT_ID = S.SHP_ID
WHERE
W.ACCOUNT_TYPE = 'I'
AND S.Schd_t <= Sysdate
AND Q.Stat_CD IN ('S','P')
ORDER BY Schd_Date);
disconnect from odbc;
QUIT;
However, after i run this i get an error saying "PROC SQL requires any created table to have at least 1 column". Any help to diagnose this issue would be appreciated.
Move the SAS syntax to the SAS side of the query. You also had an extra comma in the middle of the FROM clause. Note if you get in the habit of putting the commas (or any other continuation characters) at the beginning of the line instead of the end they will be easier for the programmers to scan and be sure they are done correctly.
create table School.TRANS_INFO as
SELECT Distinct
Schd_t AS Schd_Date format MMDDYY10.
, otb As Ship_Loc
, store_NUMBER AS store
, SHP_ID AS SHIP_ID
, store_CITY_STATE
, Stat_CD AS Status
, (PROD_CD || plt_CD) AS SKU
, ACCOUNT_TYPE as Location
from connection to odbc
(SELECT Distinct
S.Schd_t
, S.otb
, W.store_NUMBER
, S.SHP_ID
, W.store_CITY_STATE
, Q.Stat_CD
, S.PROD_CD
, S.plt_CD
, W.ACCOUNT_TYPE
FROM SHPMT_DTL S
INNER JOIN store W ON W.store_NUMBER = S.Otb_DEST_store_NBR
INNER JOIN SHP_LEG Q ON Q.SHPMT_ID = S.SHP_ID
WHERE W.ACCOUNT_TYPE = 'I'
AND S.Schd_t <= Sysdate
AND Q.Stat_CD IN ('S','P')
ORDER BY S.Schd_t
);
I am having difficulties setting up the following query where I want to:
find all the WORKORDER values in the MATERIALSCOSTACT table that have one of two specific MATERIALID values.
Then from the WORKORDER table I want to weed out all the values with a 'main replace' or 'install' DESCRIPTION and then I want to make sure I am only looking at water or sewer ASSETGROUP. I want to make sure I am only looking at records that have a WOMACOST that have occured since the first of the year.
I would like to inner join the MATERIALSCOSTACT table and the WORKORDER table on their shared WORKORDERID column.
I cant figure out how to join the first statement with teh second, and in the second statement, SQL Server is giving me a syntax error on "INNER"
select workorderid from [CityWorks].[AZTECA].[materialcostact] where materialsid = '30791' or
materialsid = '30841'
Select * from [CityWorks].[AZTECA].[WORKORDER]
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE > '2013-12-31 00:00:00.000'
INNER JOIN workorderid on [CityWorks].[AZTECA].[materialcostact].[workorderid] =
[CityWorks].[AZTECA].[WORKORDER].[workorderid]
group by assetgroup
Thank you very much to anyone who can help!
You just have your where clause in the wrong place. It needs to come after the joins.
Select * from [CityWorks].[AZTECA].[WORKORDER]
INNER JOIN workorderid on [CityWorks].[AZTECA].[materialcostact].[workorderid] =
[CityWorks].[AZTECA].[WORKORDER].[workorderid]
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE > '2013-12-31 00:00:00.000'
group by assetgroup
You may have to alias your tables or be more explicit in your where clause if those columns occur in more than one table.
I believe this is what you want:
NB: try to use aliases, they make your code easier to read.
Select *
from [CityWorks].[AZTECA].[WORKORDER] WO
JOIN [CityWorks].[AZTECA].[materialcostact] MC
on WO.[workorderid] = MC.[workorderid]
and (MC.materialsid = 30791 or MC.materialsid = 30841)
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE >= '2014-01-01'
I'm trying to query how many transaction each loyaltyID column has in AnthemTxns_Jr and what the total of all of their transactions adds up to. Right now, when I run this script, it says,
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.AnthemTxns_JR.count", or the name is ambiguous
Code:
Select DISTINCT
dbo.ANTHEM_IDS_JR.loyaltyID,
dbo.ANTHEM_IDS_JR.Military_Type,,
dbo.ANTHEM_IDS_JR.Military_Date,
dbo.AnthemTxns_JR.count(CheckTotal),
dbo.AnthemTxns_JR.sum(CheckTotal)
From
dbo.ANTHEM_IDS_JR
JOIN
dbo.AnthemTxns_JR ON dbo.ANTHEM_IDS_JR.loyaltyID = dbo.AnthemTxns_JR.loyaltyID
WHERE
Military_Type = 'Active Duty'
AND ACTIVE = 1
AND datalength(dbo.ANTHEM_IDS_JR.Military_Date) > 0
ORDER BY
loyaltyID;
Try this... It looks like you have it a bit mixed up in the select statement
Select DISTINCT
dbo.ANTHEM_IDS_JR.loyaltyID,
dbo.ANTHEM_IDS_JR.Military_Type,
dbo.ANTHEM_IDS_JR.Military_Date,
count(dbo.AnthemTxns_JR.CheckTotal) as CheckTotalCount,
sum(dbo.AnthemTxns_JR.CheckTotal) as CheckTotalSum
From
dbo.ANTHEM_IDS_JR
JOIN
dbo.AnthemTxns_JR ON dbo.ANTHEM_IDS_JR.loyaltyID = dbo.AnthemTxns_JR.loyaltyID
WHERE
Military_Type = 'Active Duty'
AND ACTIVE = 1
AND datalength(dbo.ANTHEM_IDS_JR.Military_Date) > 0
Group by
dbo.ANTHEM_IDS_JR.loyaltyID,
dbo.ANTHEM_IDS_JR.Military_Type,
dbo.ANTHEM_IDS_JR.Military_Date
ORDER BY
loyaltyID;
I want to create indexed view MyView with such t-sql
Select
o.Theme_ID as Theme_ID,
DATEADD(day, DATEDIFF(day, 0, o.Object_CreationDate), 0) as Objext_CreationDate,
Count_BIG(*) as ObjectCount, o.Object_Tonality from [dbo].Object o
inner join [dbo].Theme t on o.Theme_ID = t.Theme_ID
inner join [dbo].[ThemeWorkplace] tw on t.Theme_ID = tw.Theme_ID
inner join [dbo].Workplace w on w.Workplace_ID = tw.Workplace_ID
... where t.Theme_DeletedMark = 0
AND (w.Workplace_AccessType = 1 OR w.Workplace_AccessType = 8)
AND Object_DeletedMark = 0 ...
Group BY o.Theme_ID,o.Object_Tonality, DATEADD(day, DATEDIFF(day, 0, o.Object_CreationDate), 0)
This t-sql works fine and allows to set a clustered index on MyView.
The problem is that table ThemeWorkplace contains several records with same Theme_ID.
AND even I use GROUP BY - I get in Object_Count value that
equals: (real Object_Count value) * count(Theme_ID in ThemeWorkplace ).
I can't use DISTINCT word in t-sql, because in this case it is impossible to create index on view.
What is a suggestion to get correct results in my view ?
As you've noted, there are significant restrictions on creating an indexed view. The techniques that might help you here, such as distinct or a subquery are prohibited. I think you'll need to sacrifice materializing the view in this particular case.