Query, subquery and using as variables from subquery - sql

Is it not possible to use the "as [item] and then use the item variable in the query.
For example:
select c.category as [category],c.orderby as [CatOrder], m.masterno, m.master
,-- select OUT (select count(*) from rentalitem ri with (nolock),
rentalitemstatus ris with (nolock),
rentalstatus rs with (nolock)
where ri.rentalitemid = ris.rentalitemid
and ris.rentalstatusid = rs.rentalstatusid
and ri.masterid = m.masterid
and rs.statustype in ('OUT', 'INTRANSIT', 'ONTRUCK')) as [qtyout]
,-- select OWNED owned=
(select top 1 mwq.qty
from masterwhqty mwq
where mwq.masterid = m.masterid)
, -([owned]-[qtyout]) as [Variance]
from master m
inner join category c on c.categoryid=m.categoryid and c.categoryid=#category
inner join inventorydepartment d on c.inventorydepartment=#department
I cannot seem to use qtyout or owned when calculating variance. How can I do that?

You can also use a table variable and then reference that table variable like you are trying to do above....here's an example from MSDN
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.ModifiedDate
INTO #MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM #MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO

need to move your calculated fields into a subquery, and then use them by their alias in the outer query.
select subquery.*, -([owned]-[qtyout]) as [Variance]
from
(
select c.category as [category],c.orderby as [CatOrder], m.masterno, m.master
,-- select OUT (select count(*) from rentalitem ri with (nolock),
rentalitemstatus ris with (nolock),
rentalstatus rs with (nolock)
where ri.rentalitemid = ris.rentalitemid
and ris.rentalstatusid = rs.rentalstatusid
and ri.masterid = m.masterid
and rs.statustype in ('OUT', 'INTRANSIT', 'ONTRUCK')) as [qtyout]
,-- select OWNED owned=
(select top 1 mwq.qty
from masterwhqty mwq
where mwq.masterid = m.masterid) as [owned]
from master m
inner join category c on c.categoryid=m.categoryid and c.categoryid=#category
inner join inventorydepartment d on c.inventorydepartment=#department
) as subquery

YOu need to use a subquery:
select t.*,
([owned]-[qtyout]) as [Variance]
from (<something like your query here
) t
You query, even without the comments, doesn't quite make sense (select OUT (select . . . for isntance). But, the answer to your question is to define the base variables in a subquery or CTE and then subsequently use them.
And, you are calling the difference "variance". Just so you know, you are redefining the statistical meaning of the term (http://en.wikipedia.org/wiki/Variance), which is based on the squares of the differences.

Related

Set value in column guided by result from select. SQL Server

I have a ready select.
SELECT
[c.MySiteRole].[Id],
[c.MySiteRole].[EmployeeId],
[c.MySiteRole].[RoleId],
[c.MySiteRole].[SiteId],
[e.Site].[Id],
[e.Role].[Id],
[e.Role].[Name],
[e.Role].[RoleTypeId]
FROM
[MySiteRole] AS [c.MySiteRole]
INNER JOIN
[Site] AS [e.Site] ON [c.MySiteRole].[SiteId] = [e.Site].[Id]
INNER JOIN
[Role] AS [e.Role] ON [c.MySiteRole].[RoleId] = [e.Role].[Id]
INNER JOIN
(SELECT TOP(1) [c1].[Id]
FROM [Employee] AS [c1]
WHERE [c1].[UserName] = 'MyUserName'
ORDER BY [c1].[Id]) AS [t0] ON [c.MySiteRole].[EmployeeId] = [t0].[Id]
ORDER BY
[t0].[Id], [e.Role].[Id]
In result of this select I have a list.
Next stage I need to compare the result [e.Role].[Id] from select with few other Id and they must be here, not in other table.
"first-guid-id"
"second-guid-id"
"third-guid-id".
If in result select will be coincidence with one of this id I need set for MyColumn update true. !important - coincidence must be only with guid id from this list. For example if coincidence will be with one of them and in result [e.Role].[Id] will be other guid id - need set false for my update column. It's like "isOnlyProgrammerRoles"
Now I have my update script in this case
UPDATE [dbo].[MyTable]
SET [MyColumn] = CAST (CASE WHEN UserName like '%[^0-9]%' then 0 else 1 end AS BIT)
I need to update my script to something like this
UPDATE [dbo].[MyTable]
SELECT [c.MySiteRole].[Id],
[c.MySiteRole].[EmployeeId],
[c.MySiteRole].[RoleId],
[c.MySiteRole].[SiteId],
[e.Site].[Id],
[e.Role].[Id],
[e.Role].[Name],
[e.Role].[RoleTypeId]
FROM [MySiteRole] AS [c.MySiteRole]
INNER JOIN [Site] AS [e.Site]
ON [c.MySiteRole].[SiteId] = [e.Site].[Id]
INNER JOIN [Role] AS [e.Role]
ON [c.MySiteRole].[RoleId] = [e.Role].[Id]
INNER JOIN (SELECT TOP(1) [c1].[Id]
FROM [Employee] AS [c1]
WHERE [c1].[UserName] = 'MyUserName'
ORDER BY [c1].[Id]) AS [t0]
ON [c.MySiteRole].[EmployeeId] = [t0].[Id]
ORDER BY [t0].[Id],
[e.Role].[Id]
Compare the Result.Id with GUID id from list 'guidId', guidId', guidId'
if one or more coincidence from list(only from list + no more guid id in the result){
SET [MyColumn] = 1 like bit
}
Well, this solution doesn't follow the same table aliasing and it removes the unneeded brackets. I'm not sure what you mean by "no guid in the result...". Anyway, something like this
;with three_guid_count_cte(r_id) as (
SELECT
r.Id
FROM
MySiteRole AS msr on
INNER JOIN Site AS s ON msr.SiteId = s.Id
INNER JOIN Role AS r ON msr.RoleId = r.Id
INNER JOIN (SELECT TOP(1) c1.Id
FROM Employee AS c1
WHERE c1.UserName = 'MyUserName'
ORDER BY c1.Id) AS t0 ON msr.EmployeeId = t0.Id
INNER JOIN (values (guid1), (guid2), (guid3)) t(v) on r.Id=t.v
HAVING
COUNT(*)>1;
UPDATE m
SET [MyColumn] = CAST(1 AS BIT)
FROM
[dbo].[MyTable] m
INNER JOIN three_guid_count_cte tgc on m.????=tgc.r_id;

changing temp tables to declaring them

Just a question regards to temp tables and declaring table. If I change the temp tables 'ChangedData' and 'PackageDatatoProcess' to their own variables '#ChangedData' and '#PackageDatatoProcess', can I ask how I am suppose to change the select into statement as I have not quite done this before. Virtually I told that we can declare tables rather than using the select into but just need a bit of help with this:
select distinct * into #PackageDataToProcess from #ChangedData pp
outer apply (
select pk.Reference, pjl.PackageToJournalLinkId, j.CreatedDate, pccl.PackageCostChangeLogId from Jet2Holidays.dbo.Package pk
inner join Jet2Holidays.dbo.PackageToJournalLink pjl on pk.PackageId = pjl.PackageId
inner join Jet2Holidays.dbo.Journal j on pjl.JournalId = j.JournalId
and j.PrincipalName= iif(#AllowNonSupportChanges = 0, 'HolidaysSupport', j.PrincipalName)
inner join Jet2Holidays.dbo.BusinessProcess bp on pjl.BusinessProcessId = bp.BusinessProcessId
and bp.[Description] = iif(#AllowNonSupportChanges = 0, 'CallCentreAction', bp.[Description])
left outer join Jet2Holidays.dbo.PackageCostChangeLog pccl on pccl.PackageToJournalLinkId = pjl.PackageToJournalLinkId
where pk.Reference = pp.PackageReference
and pp.JournalID = pjl.JournalId
) as packageData
First, you declare your variable tables like so:
DECLARE #PackageDataToProcess TABLE
(
Reference UNIQUEIDENTIFIER
, PackageToJournalLinkId INT
, CreatedDate DATETIME
, PackageCostChangeLogId INT
, {other columns here}
)
DECLARE #ChangedData TABLE
(
Reference UNIQUEIDENTIFIER
, PackageToJournalLinkId INT
, CreatedDate DATETIME
, PackageCostChangeLogId INT
, {other columns here}
)
At this point you can populate your #ChangedData table like so:
INSERT #ChangedData ( Reference, PackageToJournalLinkId, CreatedDate, PackageCostChangeLogId, {other columns})
SELECT Reference, PackageToJournalLinkId, CreatedDate, PackageCostChangeLogId, {other columns}
FROM ChangedDataSource -- Table, Procedure, Function
And then you can run your code by substituting #PackageDataToProcess for #PackageDataToProcess. Here it is again with a slight re-write (from the original):
INSERT #PackageDataToProcess
select distinct pp.* from #ChangedData pp
outer apply (
select pk.Reference, pjl.PackageToJournalLinkId, j.CreatedDate, pccl.PackageCostChangeLogId from Jet2Holidays.dbo.Package pk
inner join Jet2Holidays.dbo.PackageToJournalLink pjl on pk.PackageId = pjl.PackageId
inner join Jet2Holidays.dbo.Journal j on pjl.JournalId = j.JournalId
and j.PrincipalName= iif(#AllowNonSupportChanges = 0, 'HolidaysSupport', j.PrincipalName)
inner join Jet2Holidays.dbo.BusinessProcess bp on pjl.BusinessProcessId = bp.BusinessProcessId
and bp.[Description] = iif(#AllowNonSupportChanges = 0, 'CallCentreAction', bp.[Description])
left outer join Jet2Holidays.dbo.PackageCostChangeLog pccl on pccl.PackageToJournalLinkId = pjl.PackageToJournalLinkId
where pk.Reference = pp.PackageReference
and pp.JournalID = pjl.JournalId
) as packageData
Your declared tabled will go out of scope in a similar manner to the way your non-global temporary table do.

Sql Server Selecting Distinct records and OrderBy NEWID()

this is the stored procdure, I need to select Distinct Records and display them in a random order but I am facing an error that selecting Distinct can not be used with newid(), so how can I walk around this ?
USE [OtlobODR]
GO
/****** Object: StoredProcedure [OtlobFood].[ListOffersItems] Script Date: 11/18/2012 13:01:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [OtlobFood].[ListOffersItems]
#Fk_CampaignID int
as
select distinct
CampaignID, CampaignOffers.OldPrice
, dbo.ItemSizes.IS_Id,
, dbo.Items.[Item_Description_L2] as Item_Description
, dbo.Items.[Item_Image]
, dbo.Items.[Item_Details]
, dbo.ItemSizes.[IS_Price] as Price
-- if null then it is not a featured meal
, dbo.ProviderItems.[PI_Id] as ProviderItems_PI_ID
, dbo.ItemCategories.[ItemCat_Id]
, dbo.Providers.Provider_Name_L2 as Provider_Name
, dbo.Providers.Provider_Menu_Logo
, dbo.Providers.Provider_Id
FROM Items
INNER JOIN ProviderItems ON Items.Item_Id = ProviderItems.Item_Id
INNER JOIN dbo.ItemSizes ON dbo.Items.Item_Id = dbo.ItemSizes.Item_Id
INNER JOIN CampaignOffers ON CampaignOffers.ItemID = ItemSizes.IS_Id
INNER JOIN dbo.ItemCategories ON dbo.Items.ItemCat_Id = dbo.ItemCategories.ItemCat_Id
INNER JOIN dbo.Providers ON dbo.ProviderItems.Provider_Id = dbo.Providers.Provider_Id
INNER JOIN dbo.Branches ON dbo.Providers.Provider_Id = dbo.Branches.Provider_Id
where Fk_CampaignID=#Fk_CampaignID
group by NEWID(),
CampaignID, CampaignOffers.OldPrice ,
dbo.ItemSizes.IS_Id,
dbo.Items.[Item_Description_L2],
dbo.Items.[Item_Image],
dbo.Items.[Item_Details],
dbo.ItemSizes.IS_Id,
dbo.ItemSizes.[IS_Price] ,
-- if null then it is not a featured meal
dbo.ProviderItems.[PI_Id] ,
dbo.ItemCategories.[ItemCat_Id],
dbo.Providers.Provider_Name_L2,
dbo.Providers.Provider_Menu_Logo
,dbo.Branches.Branch_Id,
dbo.Providers.Provider_Id,CampaignID,CampaignOffers.OldPrice
order by NEWID()
You need to push the SELECT DISTINCT into an inner query (at which point you can also lose the GROUP BY) then do a NEWID() in the outer query. The general form is
select
newid(), X.*
from
(
select distinct <cols>
from <tables>
where <whatever>
) X
order by 1
in your case I think this is what you want:
select
newid(), X.*
from
(
select distinct
CampaignID, CampaignOffers.OldPrice ,
dbo.ItemSizes.IS_Id,
dbo.Items.[Item_Description_L2] as Item_Description ,
dbo.Items.[Item_Image],
dbo.Items.[Item_Details],
dbo.ItemSizes.[IS_Price] as Price,
-- if null then it is not a featured meal
dbo.ProviderItems.[PI_Id] as ProviderItems_PI_ID,
dbo.ItemCategories.[ItemCat_Id],
dbo.Providers.Provider_Name_L2 as Provider_Name,
dbo.Providers.Provider_Menu_Logo,
dbo.Providers.Provider_Id
FROM
Items
INNER JOIN ProviderItems ON Items.Item_Id = ProviderItems.Item_Id
INNER JOIN dbo.ItemSizes ON dbo.Items.Item_Id = dbo.ItemSizes.Item_Id
inner join CampaignOffers ON CampaignOffers.ItemID = ItemSizes.IS_Id
INNER JOIN dbo.ItemCategories ON dbo.Items.ItemCat_Id = dbo.ItemCategories.ItemCat_Id
INNER JOIN dbo.Providers ON dbo.ProviderItems.Provider_Id = dbo.Providers.Provider_Id
INNER JOIN dbo.Branches ON dbo.Providers.Provider_Id = dbo.Branches.Provider_Id
where
Fk_CampaignID = #Fk_CampaignID
) X
order by 1
Remove the NEWID()'s from your query and surround it with
SELECT * FROM (
<your query>
) as t
ORDER BY NEWID()
This query doesn't make much sense, there is no aggregation, so what is the purpose of the group by statement? and grouping by a NEWID() is not going to get you any grouping's anyway.
Combine the superfluous group by with the distinct clause and it feels more like you have a join condition incorrect that is causing a cartesian, and you are desperately trying to use distinct and group by's to eliminate that cartesian, it certainly makes little sense to have them both in the statement, and the newid in the group by should be removed.

Only one expression can be specified in the select list

I need to get this sql query working:
SELECT TOP 15 id, thumb, width, height
FROM (SELECT vPictures.id, vPictures.thumb, vPictureCrops.width, vPictureCrops.height
FROM vPictures INNER JOIN
vPictureCrops ON vPictures.id = vPictureCrops.picid
WHERE (vPictureCrops.width = '602') AND (vPictureCrops.height = '131')
GROUP BY vPictures.id, vPictures.thumb, vPictureCrops.width, vPictureCrops.height) AS derivedtbl_1
WHERE (id NOT IN
(SELECT TOP 0 vPictures_1.id, vPictures_1.datetime, vPictures_1.url, vPictures_1.author, vPictures_1.companyID, vPictures_1.source,
vPictures_1.people, vPictures_1.text, vPictures_1.thumb, vPictures_1.logo, vPictureCrops_1.id AS Expr1, vPictureCrops_1.picid,
vPictureCrops_1.url AS Expr2, vPictureCrops_1.width, vPictureCrops_1.height
FROM vPictures AS vPictures_1 INNER JOIN
vPictureCrops AS vPictureCrops_1 ON vPictures_1.id = vPictureCrops_1.picid))
ORDER BY id DESC
Can you help me?
The error message:
"Only one expression can be specified in the select list when the subquery is not introduced with EXISTS)"
The Where (ID not IN(
The Select must only have one field are the IN can not understand which column you are trying to parse.
Eg from here
USE AdventureWorks2008R2;
GO
SELECT p.FirstName, p.LastName
FROM Person.Person AS p
JOIN Sales.SalesPerson AS sp
ON p.BusinessEntityID = sp.BusinessEntityID
WHERE p.BusinessEntityID IN
(SELECT BusinessEntityID
FROM Sales.SalesPerson
WHERE SalesQuota > 250000);
GO
Not sure what you are trying to achieve with the query anyway, can you explain the usage of the where in clause,
I can see two problems with (id NOT IN (SELECT TOP 0 vPictures_1.id, ...
only when column should be specified in the select statement after IN. For example (id NOT IN (SELECT vPictures_1.id FROM ...
even if you make it just one field vPictures_1.id the condition will always be false because of top 0.

SQL show records that don't exist in my table variable

I have a table variable that holds orderID, UnitID and OrderServiceId (it is already populated via a query with insert statement).
I then have a query under this that returns 15 columns which also include the OrderId, UnitId, OrderServiceId
I need to only return the rows from this query where the same combination of OrderId, UnitId, and OrderServiceId are not in the table variable.
You can use NOT EXISTS. e.g.
FROM YourQuery q
WHERE NOT EXISTS
(
SELECT * FROM #TableVar t
WHERE t.OrderId = q.OrderId
and t.UnitId = q.UnitId
and t.OrderServiceId=q.OrderServiceId
)
select q.*
from (
MyQuery
) q
left outer join MyTableVariable t on q.ORDERID = t.ORDERID
and q.UNITID= t.UNITID
and q.ORDERSERVICESID = t.ORDERSERVICESID
where t.ORDERID is null
You can use EXCEPT | INTERSECT operators for this (link).
Example:
(select 3,4,1
union all
select 2,4,1)
intersect
(select 1,2,9
union all
select 3,4,1)