SQL Server 2008 R2 Invalid object name error - sql

Here's the stored procedure I'm trying to implement:
Alter PROCEDURE pro_worst_supplier_test
#datey nvarchar(4), #datem nvarchar(2)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
select y.CompanyName from (SELECT s.CompanyName,(select min(t.b) from (select (round(sum(OD.Quantity * (1-OD.Discount) * OD.UnitPrice),0)) as b from [Order Details] group by ProductID) t) as q
FROM ((((Products p
inner join [Order Details] OD on p.ProductID=OD.ProductID)
inner join Categories c on p.CategoryID=c.CategoryID)
inner join Suppliers s on p.SupplierID=s.SupplierID)
inner join Orders o on o.OrderID=od.OrderID)
where c.CategoryName='Produce' AND SUBSTRING(CONVERT(nvarchar(22), o.OrderDate, 111),1,4)=#datey AND SUBSTRING(CONVERT(nvarchar(22),o.OrderDate, 111),6,2)=#datem
group by s.CompanyName) y
where q=(select MIN(q)from y)
END
GO
When I tried to execute it by
exec proc_worst_supplier_test '1998','04'
I got an error
Invalid object name 'y'

try this:
;WITH CTE as (
SELECT s.CompanyName,(select min(t.b) from (select (round(sum(OD.Quantity * (1-OD.Discount) * OD.UnitPrice),0)) as b from [Order Details] group by ProductID) t) as q
FROM ((((Products p
inner join [Order Details] OD on p.ProductID=OD.ProductID)
inner join Categories c on p.CategoryID=c.CategoryID)
inner join Suppliers s on p.SupplierID=s.SupplierID)
inner join Orders o on o.OrderID=od.OrderID)
where c.CategoryName='Produce' AND SUBSTRING(CONVERT(nvarchar(22), o.OrderDate, 111),1,4)=#datey AND SUBSTRING(CONVERT(nvarchar(22),o.OrderDate, 111),6,2)=#datem
group by s.CompanyName
)
select CompanyName from CTE where q=(select MIN(q) from CTE)

Related

How can I use the return of a select into another select in order to sum them?

My problem is that I want to sum the column of quantity with their corresponding employee ID but it doesnt let me rename the result of the query with as
Here is my query:
SELECT Orders.OrderID,Orders.EmployeeID,[Order Details].Quantity
FROM Orders INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
It doesnt let me put:
AS name (query)
or (query) AS name
In order for me to use another select query like this:
SELECT SUM([Orders Detail].Quantity) FROM queryResult Group By Orders.EmployeeID
Try this:
SELECT SUM(QUANTITY),EmployeeId FROM(
SELECT ORD.OrderID,ORD.EmployeeID,OD.Quantity
FROM Orders AS ORD
INNER JOIN DimEmployee AS DE
ON ORD.EmployeeID=DE.EmployeeID
INNER JOIN [Order Details] AS OD
ON OD.OrderID = ORD.OrderID
) AS X
Group By EmployeeId
Something like this should give you what you want.
SELECT
Orders.EmployeeID AS EmployeeID,
SUM([Order Details].Quantity) AS TotalQty
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
GROUP BY
Orders.EmployeeID
You can do this with a straight forward aggregation, or a window function to return all details. You may need to remove the OrderID from the SELECT list and GROUP BY if you don't want the results grouped at that level.
SELECT
Orders.OrderID,
Orders.EmployeeID,
EmpTotal = SUM([Order Details].Quantity)
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
GROUP BY
Orders.OrderID,
Orders.EmployeeID
SELECT
Orders.OrderID,
Orders.EmployeeID,
PartitionedTotal = SUM([Order Details].Quantity) OVER (PARTITION BY Orders.EmployeeID, Orders.OrderID) --here you may only want to partition by the EmployeeID instead of both
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID

sql server: select a NULL field that is foreign key

table "product" :
productID productNAME
21 mouse
22 keyboard
table "order" :
orderID productID
31 21
32 NULL
sql command:
SELECT dbo.[order].orderID, dbo.product.productNAME
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
result:
orderID productID
31 mouse
QUESTION:
how to show the second order? (while productID of that order is NULL, but that order existed)
is there any trick for that?
i tried these:
WHERE (dbo.[order].orderID = 32) OR
(dbo.product.productID IS NULL)
and
SELECT dbo.[order].orderID, ISNULL(dbo.product.productNAME, ' - ') AS Expr1
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
but the same result
The obvious solution is left join:
SELECT o.orderID, p.productNAME
FROM dbo.[order] o LEFT JOIN
dbo.product p
ON o.productID = p.productID;
You could also write:
SELECT o.orderID, p.productNAME
FROM dbo.[order] o JOIN
dbo.product p
ON o.productID = p.productID OR o.productID IS NULL;
The OR will probably affect the performance of this query.
It's because you're using an Inner Join, specifically matched on ProductID. Because one is NULL of course it will not match. If you wish to return all results from the Order table regardless of whether there is a match in the product table, you need to look at other types of Joins, such as LEFT and RIGHT OUTER JOINS.
A classic outer join example!
SELECT dbo.[order].orderID, ISNULL(dbo.product.productNAME, ' - ') AS Expr1
FROM dbo.[order]
LEFT JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
you have to use OR condition along with inner join.
SELECT o.orderID
,p.productNAME
FROM dbo.[order] o
INNER JOIN dbo.product p ON o.productID = p.productID
OR o.productID IS NULL;
The obvious/classic solution is UNION:
SELECT dbo.[order].orderID, dbo.product.productNAME
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
UNION
SELECT dbo.[order].orderID, '{{NONE}}' AS productNAME
FROM dbo.[order]
WHERE dbo.[order].productID IS NULL;

Update column with a subquery

ALTER TABLE order_t ADD Totalfixed DECIMAL(7,2);
UPDATE Order_t
SET Totalfixed = (
SELECT orderid, SUM(price * quantity) AS tf
FROM
orderline ol,
product p
WHERE
ol.productid = p.productid
AND ol.orderid = orderid
GROUP BY orderid
);
Everything works fine separately but I get:
operand should contain 1 column
And if I remove orderid from the subquery, I get:
subquery returns more than 1 row
Is there anyway to make this work without a join?
Regardless of the database, the context requires a scalar subquery. This means avoid the group by and return only one column:
UPDATE Order_t
SET Totalfixed = (
SELECT SUM(price * quantity) AS tf
FROM orderline ol JOIN
product p
ON ol.productid = p.productid
WHERE ol.orderid = Order_t.orderid
);
I also fixed the JOIN syntax (always use explicit joins) and the correlation clause so it refers to the outer query.
UPDATE A
SET Totalfixed = SUM(price * quantity)
FROM Order_t A
INNER JOIN orderline ol ON ol.orderid = A.orderid
INNER JOIN product p ON ol.productid = p.productid

Insufficient output from SQL query

I'm using the northwind db: http://dev.assets.neo4j.com.s3.amazonaws.com/wp-content/uploads/Northwind_diagram.jpg
I have to output all orders placed by CustomerID ALFKI with more than one unique product. I get the correct orders out, but I can't figure out why it's only printing one product name per order.
My query:
SELECT a.OrderID, p.ProductName
FROM Products p
INNER JOIN 'Order Details' a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
You need the GROUP BY and HAVING to be part of a subquery, with your primary query selecting the detail using the list of OrderIDs returned from the subquery as filter criteria. Try the following syntax for T-SQL:
SELECT
a.OrderID,
p.ProductName
FROM
Products p
INNER JOIN [Order Details] a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE
a.OrderID IN
(
SELECT a.OrderID
FROM [Order Details] a
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
)

Drastic CTE query speed degradation on actions in outer select

I have a complex report (Similar to example below) it returns with only 52 items in 42 seconds (Slow but does complex joins) it drastically slows down when I do the following:
Add a column in the outer select to get a serialized list of items for
each item in the result (Adds 150 seconds) - See function.
Insert result into a variable table (Adds 120 seconds), I though hoped flattening it would reduce the (1) issue but no cigar.
How I understand the execution is that the where is executed first then logic in the select (Should only be done for the 52 result items). However if I run that exact 52 items with the (1) scenario it only takes 7 seconds vs the added 150 when using it on the outer CTE select.
Why could this be and how can I add the column without the bloated execution time?
CREATE FUNCTION PriorShippers
(
#customerId nchar(5)
)
RETURNS varchar(500)
AS
BEGIN
DECLARE #return varchar(500);
with data as
(
select distinct S.CompanyName from Customers C
join Orders O on C.CustomerID = O.CustomerID
join Shippers S on O.ShipVia = S.ShipperID
where C.CustomerID = #customerId
) select #return = STUFF((select CompanyName + ' ' from data FOR XML PATH('')),1,0,'')
return #return
END
The query (I used Northwind database - Install Instructions here for SQL 2012)
DECLARE #categories TABLE
(
Name varchar(100),
SourceCountry varchar(100)
);
insert into #categories VALUES ('Seafood', 'US');
insert into #categories VALUES ('Beverages', 'US');
insert into #categories VALUES ('Condiments', 'US');
insert into #categories VALUES ('Dairy Products', 'India');
insert into #categories VALUES ('Grains/Cereals', 'India');
with data as
(
select C.CustomerID, C.CompanyName,
(CASE WHEN EXISTS(select * from Orders O where O.CustomerID = C.CustomerID) THEN
(select count(distinct CAT.CategoryID) from Orders O
join [Order Details] OD on O.OrderID = OD.OrderID
join Products P on OD.ProductID = P.ProductID
join Categories CAT on P.CategoryID = CAT.CategoryID
where EXISTS(select * from #categories where Name = CAT.CategoryName AND SourceCountry = 'US'))
ELSE 0 END) as 'US Orders',
(CASE WHEN EXISTS(select * from Orders O where O.CustomerID = C.CustomerID) THEN
(select count(distinct CAT.CategoryID) from Orders O
join [Order Details] OD on O.OrderID = OD.OrderID
join Products P on OD.ProductID = P.ProductID
join Categories CAT on P.CategoryID = CAT.CategoryID
where EXISTS(select * from #categories where Name = CAT.CategoryName AND SourceCountry = 'India'))
ELSE 0 END) as 'India Orders'
from Customers C
) select top 10 CompanyName, [US Orders], [India Orders]
-- Below: Adding this have significant slow down
, dbo.PriorShippers(CustomerID)
from data where [US Orders] > 0 Order By [US Orders]
You are executing a user-defined function for each selected row. In short, don't do that.
Move the code in the function into a DTE directly within the report.
Also, I noticed that the joins for your counts are identical. They look like prime candidates for a third DTE that you could simply join to to further improve the performance of the overall query.