I am not author of the stored procedure and I am wondering why they used UNION in SELECT statement when selecting from the derived table ...
If I comment out the whole UNION ALL SELECT statement, I get the same result with the same basically performance.
So I am just wonder why it is there? What kind of trick does it makes?
Below is the whole stored procedure in case I am missing something
ALTER PROCEDURE [dbo].[rptActivityLog] --'1/1/2016', '2/3/2016'
(#DateFrom datetime = null,
#DateTo datetime = null,
#UserGuid uniqueidentifier = null,
#CurrentUserGuid uniqueidentifier = NULL)
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE #UserID SMALLINT
SELECT #UserID = UserID
FROM tblUsers
WHERE (UserGUID = #UserGuid)
DECLARE #ValidOfficeGuids TABLE (OfficeGuid uniqueidentifier primary key)
--if user is in tblUserQuotingOffice then use only that Office
--otherwise they will have access to all offices
IF EXISTS (SELECT OfficeGuid
FROM tblUserQuotingOffice
WHERE UserGuid = #CurrentUserGuid)
BEGIN
INSERT INTO #ValidOfficeGuids
SELECT OfficeGuid
FROM tblUserQuotingOffice
WHERE UserGuid = #CurrentUserGuid
END
ELSE
BEGIN
INSERT INTO #ValidOfficeGuids
SELECT OfficeGUID
FROM tblClientOffices
END
DECLARE #compareDateFrom DATETIME
set #compareDateFrom = CAST(CONVERT(VARCHAR(50), #DateFrom, 101) AS DATETIME)
declare #compareDateTo datetime
set #compareDateTo = DateAdd(ms, -2, DateAdd(d, 1, CAST(CONVERT(VARCHAR(50), DATEADD(day, 7, #DateTo), 101) AS DATETIME)))
--First get the log entries
declare #logResults table
(
ID int primary key not null
, IdentifierGuid uniqueidentifier
)
insert into #logResults
select
l.ID
, l.IndentifierGuid
from
tblLog l
where
l.ActionDate between #compareDateFrom and #compareDateTo
and l.IndentifierGuid is not null
select
distinct
T.UserName
, T.ControlNo
, T.InsuredPolicyName
, Replace(Replace(T.[Action],Char(10),''),Char(13),'') as [Action]
, T.ActionDate
, T.LineName as LOB
from
(
select
u.UserName
, q.ControlNo
, q.InsuredPolicyName
, l.[Action]
, l.ActionDate
, ll.LineName
, l.UserID
from
#logResults r
inner join tblLog l on r.ID = l.ID
inner join tblUsers u on l.UserID = u.UserID
inner join tblQuotes q on r.IdentifierGuid = q.QuoteGUID
inner join lstLines ll on q.LineGUID = ll.LineGUID
-- WHY DO WE USE BELOW UNION STATEMENT??????????????????????????????????
union
select
u.UserName
, q.ControlNo
, q.InsuredPolicyName
, l.[Action]
, l.ActionDate
, ll.LineName
, l.UserID
from
#logResults r
inner join tblLog l on r.ID = l.ID
inner join tblUsers u on l.UserID = u.UserID
inner join tblQuotes q on r.IdentifierGuid = q.ControlGUID
inner join lstLines ll on q.LineGUID = ll.LineGUID
) T
WHERE IsNull(#UserID, T.UserID) = T.UserID
order by
T.ActionDate
There is a difference in the join with tblQuotes, looks like the union is meant to union two different datasets (one for QuoteGUIDs and one for ControlGUIDs)
Related
The literature says that the declare statement is not compatible with creating a View. How do I get around it?
My declare statement looks like:
DECLARE #risk_5 TABLE (Code VARCHAR(100));
INSERT INTO #risk_5 (Code) VALUES ('AA'),('BB'),('CC');
and is then used within a select statement:
SELECT
id,
CASE
WHEN a.[10_2_1_Country] IN (SELECT Code from #risk_5)
THEN '3'
END AS Risk_Country5
FROM x
The recommendation is to pack the declare into a CTE or a stored procedure.
With both these recommendations though, I do not understand how to connect the two? What am I missing?
If you need to use variable try to use stored procedures, if you write a select query in the stored procedure you can get the data too. And you can use declare inside.
I use this way in my solution e.g.
CREATE PROCEDURE [dbo].[GetLoadSiteMass]( #month INT,
#year int,
#storageId int,
#parent nvarchar(50),
#materialSourceId nvarchar(100),
#complexIds nvarchar(50))
AS
BEGIN
DECLARE #MonthPrev int
DECLARE #YearPrev int
SET #MonthPrev = CASE WHEN #Month = 1 THEN 12 ELSE #Month - 1 END
SET #YearPrev = CASE WHEN #Month = 1 THEN #Year - 1 ELSE #Year END
declare #WagonLoadSiteId int
set #WagonLoadSiteId = (select top 1 CarriageLoadSiteId from CarriageLoadSite where LoadSiteType = 2);
DECLARE #loadSide nvarchar(10), #result decimal(18,3)
SET #loadSide=cast( #storageId as nvarchar(50));
WITH CarriageLoadSiteTreeView (
[CarriageLoadSiteId],RootId,RootName,[Code], Name, ParentID, [LoadSiteType],IsDelete,
CodeSAP,DepartmentId, Capacity, MinLimit, MaxLimit, LoadSitePlaceTypeId) AS
(
SELECT [CarriageLoadSiteId],
[CarriageLoadSiteId] RootId,
Name RootName,
[Code],
Name,
ParentID,
[LoadSiteType],
[IsDelete],
CodeSAP,
DepartmentId,
Capacity,
MinLimit,
MaxLimit,
LoadSitePlaceTypeId
FROM CarriageLoadSite WITH(NOLOCK)
WHERE ISNULL(ParentID,0) =isnull(#storageId,0) AND Isdelete!=1
UNION ALL
SELECT d.[CarriageLoadSiteId],
q.RootId RootId,
RootName RootName,
d.[Code],
d.Name,
d.ParentID,
d.[LoadSiteType],
d.[IsDelete],
d.CodeSAP,
d.DepartmentId,
d.Capacity,
d.MinLimit,
d.MaxLimit,
d.LoadSitePlaceTypeId
FROM CarriageLoadSite AS d WITH(NOLOCK)
INNER JOIN CarriageLoadSiteTreeView AS q ON d.ParentID = q.[CarriageLoadSiteId] WHERE d.IsDelete!=1
)
SELECT
ComplexId,
RootId Id,
cast(RootId as nvarchar(8))+'|Sclad'+IIF(RootId=max(R.CarriageLoadSiteId),'|finish','') [Uid],
RootName CarriageLoadSiteName,
ROUND(SUM(AMOUNT-movement-consumption)/1000,3) Amount,
cast(1 as bit) hasChildren,
T.FullPathId Path,
UparentId=IIF(#parent is null,'',#parent),
[Type]=0,
Petal = IIF(RootId=max(R.CarriageLoadSiteId),'|Sclad|finish','')
FROM (
SELECT
RootId
,RootName
,t.CarriageLoadSiteId
,t.MaterialId
,YEAR(t.Period) [Year]
,MONTH(t.Period) [Month]
,round( case when (t.Amount=0 or t.Amount is null) and (tt.Type=0 or [TypeAmountCarriage]=1 )then carr.[CertifNetto]else t.Amount end ,0 )[Amount]
,t.UnitId
, CarriageId
, tt.TurnoverTypeId
,round(dbo.GetMovementByTurnOverWithTempValue(t.turnoverid),5) movement
,dbo.GetConsumptionByTurnOver(t.turnoverid) consumption
,0 stockBegin
,round(t.Amount,0 ) CommingAmount
,case when (t.Amount=0 or t.Amount is null) and tt.Type=0 then 1 else 0 end [IsNotConfirmed]
,[TypeAmountCarriage]
,M.ComplexId
FROM Turnover t WITH(NOLOCK)
INNER JOIN TurnoverType tt ON tt.TurnoverTypeId = t.TurnoverTypeId
INNER JOIN CarriageLoadSiteTreeView l ON l.CarriageLoadSiteId = t.CarriageLoadSiteId
INNER JOIN [Carriages] carr on carr.[CarriagesID]=t.[CarriageId]
INNER JOIN Material M on M.MaterialID=t.MaterialId
WHERE YEAR(t.Period) = #Year AND
MONTH(t.Period) = #Month AND
l.LoadSiteType = 0 AND
tt.type in (0,5,4) AND
isclear=0 AND
M.MaterialSourceID in (select value from string_split(#materialSourceId, ','))
UNION ALL
SELECT RootId
,RootName
,s.CarriageLoadSiteId
,s.MaterialId
,#Year [Year]
,#Month [Month]
,round(s.Amount,0)
,s.UnitId
,CarriageId
,[TurnoverTypeId]
,round(dbo.GetMovementByStock(s.StockId),5) movement
,dbo.GetConsumptionByStock(s.StockId) consumption
,round(s.Amount,0)-s.spendStock
,0
,0 [IsNotConfirmed]
,[TypeAmountCarriage]
,M.ComplexId
FROM Stock s
INNER JOIN CarriageLoadSiteTreeView l ON l.CarriageLoadSiteId = s.CarriageLoadSiteId
INNER JOIN Material M on M.MaterialID=s.MaterialId
WHERE s.[Year] = #YearPrev AND
s.[Month] = #MonthPrev AND
s.[Type] = 0 AND
l.LoadSiteType = 0 AND
amount >0 AND
isclear=0 AND
M.MaterialSourceID in (select value from string_split(#materialSourceId, ','))
) as R
INNER JOIN CariageLoadSiteTree T on T.CarriageLoadSiteId=RootId
INNER JOIN string_split(#complexIds, ',') MM ON CAST(MM.value AS int) = R.ComplexId
WHERE AMOUNT-movement-consumption>10
GROUP BY RootName,RootId,ComplexId, T.FullPathId
ORDER BY RootName
Any suggstion/ solution for this problem ?
The multi-part identifier "iis.sourceId" could not be bound.
ALTER PROCEDURE [dbo].[InstrumentSourceSnapSelector]
#searchedString nvarchar(100) = null
, #at datetime
AS
BEGIN
DECLARE #sql as nvarchar(4000)
DECLARE #ParmDefinition nvarchar(500);
SET #at=dateadd(MILLISECOND, -datepart(MILLISECOND, #at), isnull(#at,getdate())) --on tronque les ms
CREATE TABLE #TEMP
(
SourceId UNIQUEIDENTIFIER,
instrumentIdentifierId UNIQUEIDENTIFIER,
instrumentId UNIQUEIDENTIFIER,
vacationId UNIQUEIDENTIFIER,
MaxReqTime DATETIME
)
INSERT INTO #TEMP
SELECT
SourceId,
instrumentIdentifierId,
instrumentId,
vacationId,
max(requestTime) as MaxReqTime
FROM
(instrumentSourceSnap inst
INNER JOIN
VacationTask T
ON inst.vacationTaskId = T.id)
GROUP BY
SourceId,instrumentIdentifierId, instrumentId, vacationId
SELECT DISTINCT
iss.id
, i.name AS Name
, s.name AS sourceName
, d.name AS identifier
, ii.value AS identifierValue
, v.name AS Vacation
FROM
instrumentSourceSnap iss
INNER JOIN #TEMP T
ON
T.sourceId = iis.sourceId AND
T.instrumentIdentifierId = iis.instrumentIdentifierId AND
T.instrumentId = iis.instrumentId AND
T.MaxReqTime = iis.ReuqestTime
INNER JOIN vacationTask vt ON vt.id = iss.vacationTaskId
INNER JOIN vacation v ON v.id = vt.vacationId
INNER JOIN instrument i ON i.id = iss.instrumentId
INNER JOIN source s ON s.id = iss.sourceId
INNER JOIN instrumentIdentifier ii ON ii.instrumentId=i.id
INNER JOIN identifier d ON d.Id=ii.identifierId
INNER JOIN instrumentSource si ON si.instrumentId = i.id and si.sourceId = s.id
END
GO
Just like the comments said, replaced all iis with iss as iss is the alias for instrunmentSourceSnap.
ALTER PROCEDURE [dbo].[InstrumentSourceSnapSelector]
#searchedString nvarchar(100) = null
, #at datetime
AS
BEGIN
DECLARE #sql as nvarchar(4000)
DECLARE #ParmDefinition nvarchar(500);
SET #at=dateadd(MILLISECOND, -datepart(MILLISECOND, #at), isnull(#at,getdate())) --on tronque les ms
CREATE TABLE #TEMP
(
SourceId UNIQUEIDENTIFIER,
instrumentIdentifierId UNIQUEIDENTIFIER,
instrumentId UNIQUEIDENTIFIER,
vacationId UNIQUEIDENTIFIER,
MaxReqTime DATETIME
)
INSERT INTO #TEMP
SELECT
SourceId,
instrumentIdentifierId,
instrumentId,
vacationId,
max(requestTime) as MaxReqTime
FROM
(instrumentSourceSnap inst
INNER JOIN
VacationTask T
ON inst.vacationTaskId = T.id)
GROUP BY
SourceId,instrumentIdentifierId, instrumentId, vacationId
SELECT DISTINCT
iss.id
, i.name AS Name
, s.name AS sourceName
, d.name AS identifier
, ii.value AS identifierValue
, v.name AS Vacation
FROM
instrumentSourceSnap iss
INNER JOIN #TEMP T
ON
T.sourceId = iss.sourceId AND
T.instrumentIdentifierId = iss.instrumentIdentifierId AND
T.instrumentId = iss.instrumentId AND
T.MaxReqTime = iss.ReuqestTime
INNER JOIN vacationTask vt ON vt.id = iss.vacationTaskId
INNER JOIN vacation v ON v.id = vt.vacationId
INNER JOIN instrument i ON i.id = iss.instrumentId
INNER JOIN source s ON s.id = iss.sourceId
INNER JOIN instrumentIdentifier ii ON ii.instrumentId=i.id
INNER JOIN identifier d ON d.Id=ii.identifierId
INNER JOIN instrumentSource si ON si.instrumentId = i.id and si.sourceId = s.id
END
GO
Create a stored procedure that passes in the SalesOrderID as a parameter.
This stored procedure will return the SalesOrderID, Date of the transaction, shipping date, city and state. It is not running
Ans:
Create PROCEDURE proc_findProductInfo
#SalesOrderID int,
#SalesOrderOut int OUTPUT,
#OrderDate datetime OUTPUT,
#ShipDate datetime OUTPUT,
#CityState varchar(100) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #SalesOrderOut = #SalesOrderID
SET #OrderDate = (SELECT OrderDate FROM SALES.SalesOrderHeader )
SET #ShipDate = (SELECT ShipDate FROM Sales.SalesOrderHeader)
SET #CityState = (SELECT a.City, st.Name
FROM Sales.SalesOrderHeader s
INNER JOIN Person.Address a ON s.ShipToAddressID = a.AddressID
INNER JOIN Person.StateProvince st ON s.TerritoryID = st.TerritoryID
WHERE SalesOrderID = #SalesOrderID)
END
DECLARE #OrderNum int, #Date datetime, #qty1 int, #Date1 datetime
EXEC proc_findProductInfo 63936,
#SalesOrderOut = #OrderNum OUTPUT,
#OrderDate = #Date OUTPUT,
#ShipDate = #date1,
#CityState = #qty1 output
SELECT #OrderNum, #date, #qty1, #Date1
Error Message:
Msg 116, Level 16, State 1, Procedure proc_findProductInfo, Line 25
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS
You're making this way harder than it needs to be:
Create PROCEDURE proc_findProductInfo
#SalesOrderID int
AS
BEGIN
SET NOCOUNT ON;
SELECT s.SalesOrderID, s.OrderDate, s.ShipDate, a.City,st.Name
FROM Sales.SalesOrderHeader s
INNER JOIN Person.Address a ON s.ShipToAddressID = a.AddressID
INNER JOIN Person.StateProvince st ON s.TerritoryID=st.TerritoryID
WHERE s.SalesOrderID = #SalesOrderID
END
I'm not even sure you need the StateProvince table here... the question probably allows you to trust the Address record.
It is complaining about the following
SET #CityState = (
SELECT a.City,st.Name
You are selecting both City and State Name and trying to assign it to a variable.
You either need to concatenate or coalesce them into them into a single output or alternatively use the below type of select to assign each one to a variable.
select
#var1 = field1,
#var2 = field2,
...
As below
SET #SalesOrderOut = #SalesOrderID
SELECT #OrderDate = s.OrderDate,
#ShipDate = s.ShipDate,
#CityState = CONCAT(a.City, ", ", st.Name)
FROM Sales.SalesOrderHeader s
inner JOIN Person.Address a
ON s.ShipToAddressID = a.AddressID
inner JOIN Person.StateProvince st
on s.TerritoryID=st.TerritoryID
WHERE SalesOrderID = #SalesOrderID
I have a variable in my report which holds 2 possible values: 'monthly' and 'daily'. How can I put this variable (lets call it #reportModel). I think it should be somewhere in GROUP BY clause, but don't know how should it look like.
DECLARE #reportModel VARCHAR(10)
SET #reportModel = 'monthly'
SELECT P.product, SUM(O.price * O.quantity), O.orderDate
FROM Products AS P
INNER JOIN Orders AS O ON P.ID = O.ID
And what now?
How about a stored procedure to handle this, something like.....
CREATE PROCEDURE rpt_GetData
#reportModel VARCHAR(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
IF (#reportModel = 'daily')
BEGIN
SET #Sql = N' SELECT P.product
, SUM(O.price * O.quantity) AS Total
, O.orderDate
FROM Products AS P
INNER JOIN Orders AS O ON P.ID = O.ID
GROUP BY P.product , O.orderDate'
Exec sp_executesql #Sql
END
ELSE IF (#reportModel = 'monthly')
BEGIN
SET #Sql = N' SELECT P.product
, SUM(O.price * O.quantity) AS Total
, MONTH(O.orderDate) AS [Month]
FROM Products AS P
INNER JOIN Orders AS O ON P.ID = O.ID
GROUP BY P.product, MONTH(O.orderDate)'
Exec sp_executesql #Sql
END
END
Adding this as an answer because I mentioned it in the comments in #M.Ali's answer.
So I would suggest you change thinking slightly with one of these options.
Two reports - Simply make a report for daily and another for monthly. Now you have no worries with complex SQL etc.
Make 2 stored procedures, one with the GROUP BY daily and one monthly. Then in your SSRS dataset, create an expression for you SQL that chooses the procedure based on parameter:
=IIf(Parameters!reportModel.Value = "monthly", "GetMonthlyData", "GetDailyData")
I would put it in the Group On Expression of the table or chart rather than doing it in the query.
=IIF(Parameters!reportModel.Value = "monthly", Month(Fields!orderDate.Value), Fields!orderDate.Value)
If you'd rather do it in the query and don't want to wait for DBAs to get around to deploying a Stored Procedure (not to mention maintaining it whenever there's a change), you could use your parameter in a CASE like:
SELECT P.product, SUM(O.price * O.quantity),
CASE WHEN #reportModel = 'monthly' THEN CAST(MONTH(O.orderDate) AS VARCHAR(12))
ELSE CAST(O.orderDateAS VARCHAR(12)) END AS DT
FROM WORKFLOW_SHARED.MAIN.VW_CLAIMSOVERPAYMENT
WHERE DATECOMPLETED > '7/1/2015'
GROUP BY P.product,
CASE WHEN #reportModel = 'monthly' THEN CAST(MONTH(O.orderDate) AS VARCHAR(12))
ELSE CAST(O.orderDateAS VARCHAR(12)) END
This way you don't have to maintain two separate reports.
How about something simple like this
select
P.product
,Total = sum(O.price * O.quantity)
, O.orderDate
from
Products as P
inner join Orders as O on P.ID = O.ID
where
#reportModel = 'daily'
union all
select
P.product
,Total = sum(O.price * O.quantity)
,[Month] = MONTH(O.orderDate)
from
Products as P
inner JOIN Orders as O on P.ID = O.ID
group by
P.product
,[Month] = MONTH(O.orderDate)
where
#reportModel = 'monthly'
I'm writing an SQL query as follows:
ALTER proc [dbo].[Invoice_GetHomePageInvoices] (
#AreaIdList varchar(max)
, #FinancialYearStartDate datetime = null
, #FinancialYearEndDate datetime = null
) as
set nocount on
select *
from Invoice i
left outer join Organisation o on i.OrganisationId = o.Id
left outer join Area a on i.AreaId = a.Id
where i.InvoiceDate BETWEEN #FinancialYearStartDate AND #FinancialYearEndDate
The #AreaIdList parameter is going to be in the format "1,2,3" etc.
I'm wanting to add a line which will only return invoices who have area id equal to any of the ids in #AreaIdList.
I know how to do a statement if it was on areaId to search on ie. where i.AreaId == areaId problem is now I have this list I got to compare for every area Id in #AreaIdList.
Can anybody tell me how you would go about this?
Unpack your ID list to a table and use where AreadID in (select ID from ...)
ALTER proc [dbo].[Invoice_GetHomePageInvoices] (
#AreaIdList varchar(max)
, #FinancialYearStartDate datetime = null
, #FinancialYearEndDate datetime = null
) as
set nocount on
set #AreaIdList = #AreaIdList+','
declare #T table(ID int primary key)
while len(#AreaIdList) > 1
begin
insert into #T(ID) values (left(#AreaIdList, charindex(',', #AreaIdList)-1))
set #AreaIdList = stuff(#AreaIdList, 1, charindex(',', #AreaIdList), '')
end
select *
from Invoice i
left outer join Organisation o on i.OrganisationId = o.Id
left outer join Area a on i.AreaId = a.Id
where i.InvoiceDate BETWEEN #FinancialYearStartDate AND #FinancialYearEndDate and
i.AreadID in (select ID from #T)