Error with sub query using ROW_NUMBER() - sql-server

Good day,
In a WHILE statement I am running, one of the variable assignments I'm attempting is to use a sub query in conjunction with row_number() to pull out each specific ID from a column and sum a monetary value from another table, per each ID. I am working in MS SQL 2008.
Here is the query I have so far:
SET #value =(SELECT PaymentAmount FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY C.CategoryID ASC) AS RowNum,
SUM(O.PaymentAmount)
FROM Orders O
INNER JOIN OrderDetails OD ON O.OrderID = OD.OrderID
INNER JOIN Products_Joined PJ ON OD.ProductCode = PJ.ProductCode
INNER JOIN Categories_Products_Link CPL ON PJ.ProductID = CPL.ProductID
INNER JOIN Categories C ON CPL.CategoryID = C.CategoryID
GROUP BY C.CategoryID
) AS Num
WHERE RowNum = #counter)
The error I'm running into is in regards to no column was specified for column 2 of 'Num'.
Thoughts? Ideas? Thanks for your time!

Related

How do I get the most updated data from the database based on the entry date for various entry ID that is multiple rows

I have 3 tables, namely CALCULATED INPUT, RAW MATERIAL INPUT and COMPANY
select * from [LTBU_MKT_RAW_CALULATED_DATA] e
inner join
(select t2.COMPANY_ENTRY_ID, t2.ENTRY_ID from LTBU_MKT_RAW_MAT_INPUT as t2) b on b.ENTRY_ID = e.ENTRY_ID
inner join
(select h.[COMPANY],h.[GUID] from LTBU_MKT_COMPANY as h) g on b.COMPANY_ENTRY_ID = g.GUID
(Select c.COMPANY,Max(t1.ENTRY_DATE) as MaxDate
from [inet].[dbo].[LTBU_MKT_RAW_CALULATED_DATA] t1
inner join
(select t2.COMPANY_ENTRY_ID, t2.ENTRY_ID from LTBU_MKT_RAW_MAT_INPUT as t2) b on b.ENTRY_ID = t1.ENTRY_ID
inner join
(select t3.[COMPANY],t3.[GUID] from LTBU_MKT_COMPANY as t3) c on b.COMPANY_ENTRY_ID = c.GUID
inner join
(SELECT t2.ENTRY_ID,t2.CHEMICAL_NAME,t2.CHEMICAL_QTY_KG,t2.CHMEICAL_CAL_PRICE,t2.CHMEICAL_PROCESS from [inet].[dbo].[LTBU_MKT_RAW_CALULATED_DATA] as t2) a on a.ENTRY_ID = t1.ENTRY_ID
group by c.COMPANY)
But it not able to combine all the information due to the MAX(ENTRY_Date)
Any help or comments is appreciated.
You can use a window function in the order by. Something like...
order by row_number() over (partition by ENTRY_ID order by ENTRY_Date desc)
I’m not sure which ENTRY_ID you want to use since more than one table has it. Be sure you reference it accordingly.

Rows with highest values from second and third tables

I have three linked tables in SQL Server (Customers, Policies and Claims), and need to get a record for each Customer showing their most recent Policy, and within that Policy, their most recent Claim. The highest PolicyID for the Customer is their most recent Policy, and the highest ClaimID is the most recent Claim for the Policy.
I have the following query to show all Policies/Claims, but how do I restrict them to the most recent/highest IDs?
SELECT C.CustomerID, C.FirstName, C.LastName, P.PolicyID, P.PolicyDate, P.PolicyType, CL.ClaimID, CL.ClaimDate, CL.ClaimDescription
FROM Customers C INNER JOIN Policies P ON C.CustomerID = P.CustomerID
INNER JOIN Claims CL ON P.PolicyID = CL.PolicyID
try this,
;WITH CTE AS
(
SELECT C.CustomerID, C.FirstName, C.LastName, P.PolicyID, P.PolicyDate, P.PolicyType, CL.ClaimID, CL.ClaimDate, CL.ClaimDescription
,ROW_NUMBER() OVER(PARTITION BY C.CustomerID ORDER BY P.PolicyID DESC) PolicyOrder
,ROW_NUMBER() OVER(PARTITION BY C.CustomerID, P.PolicyID ORDER BY CL.ClaimID DESC) ClaimOrder
FROM Customers C INNER JOIN Policies P ON C.CustomerID = P.CustomerID
INNER JOIN Claims CL ON P.PolicyID = CL.PolicyID
)
SELECT
*
FROM CTE c
WHERE c.PolicyOrder = 1
AND c.ClaimOrder = 1

select count over partition by

I am learning window functions in sql server. I am using AdventrueWorks2012 database for practice. I want to calculate total number of sales and purchases for each item in the store.
The classic solution can be like
SELECT ProductID,
Quantity,
(SELECT Count(*)
FROM AdventureWorks.Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderDetail.ProductID = p.ProductID) TotalPurchases,
(SELECT Count(*)
FROM AdventureWorks.Sales.SalesOrderDetail
WHERE SalesOrderDetail.ProductID = p.ProductID) TotalSales
FROM (SELECT DISTINCT ProductID,
Quantity
FROM AdventureWorks.Production.ProductInventory) p
Trying to convert to window functions gives me wrong results:
SELECT DISTINCT d.ProductID,
Quantity,
Count(d.ProductID)
OVER(
PARTITION BY d.ProductID) TotalPurchases,
Count(d2.ProductID)
OVER(
PARTITION BY d2.ProductID) TotalSales
FROM (SELECT DISTINCT ProductID,
Quantity
FROM AdventureWorks.Production.ProductInventory) p
INNER JOIN AdventureWorks.Purchasing.PurchaseOrderDetail d
ON p.ProductID = d.ProductID
INNER JOIN AdventureWorks.Sales.SalesOrderDetail d2
ON p.ProductID = d2.ProductID
ORDER BY d.ProductID
Why this is wrong? How can I correct it?
You should change INNER JOIN to LEFT JOIN
Because when you inner join, result will miss productid which from ProductInventory table does not have PurchaseOrderDetail or SalesOrderDetail.

create sql query to fetch repeat column values within time frame

Can someone help me with this query? I want to get the result of all the customer_id which repeats more than once in 24hrs
SELECT
O.Order_No, O.Customer_ID, O.DateOrdered, O.IPAddress,
C.FirstName, C.LastName, CD.nameoncard
FROM
Order_No O
INNER JOIN
CardData CD ON O.card_id = CD.id
INNER JOIN
Customers C ON O.customer_id = C.customer_id
ORDER BY
O.order_no desc
adding more details..
so suppose order with customer id xx was placed on 04/23 2:30 pm and again 2nd order was placed with same customer Id xx on same day 04/23 5:30 pm.
i want the query to return me customer Id xx
Thanks
select Customer_ID, CAST(DateOrdered as Date) DateOrdered, count(*) QTDE
from Order_No
group by Customer_ID, CAST(DateOrdered as Date)
having count(*) > 1
To get the customers who have orders issued after the first one, then you could use the following query:
select distinct A.Customer_ID
from Order_No A
inner join (select Customer_ID, min(DateOrdered) DateOrdered from Order_No group by Customer_ID ) B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered - B.DateOrdered <= 1
and A.DateOrdered > B.DateOrdered
SQL Fiddle
To get all customers that have ANY TIME more than one order issued in period less or equal than 24h
select distinct A.Customer_ID
from Order_No A
inner join Order_No B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered > B.DateOrdered
and A.DateOrdered - B.DateOrdered <= 1
SQL Fiddle
Self-join:
SELECT distinct O.Customer_ID
FROM
Order_No O
inner join Order_No o2
on o.customerID = o2.customerID
and datediff(hour, o.DateOrdered, o2.DateOrdered) between 0 and 24
and o.Order_No <> o2.Order_No
This will return all customer_IDs that have ever placed more than one order in any 24 hour period.
Edited to add the join criteria that the matching records should not be the same record. Should return customers who placed two different orders at the same time, but not customers who placed only one order.

Alias name issue in SQL

I was trying to write a query for the SQL Server sample DB Northwind. The question was: "Show the most recent five orders that were purchased by a customer who has spent more than $25,000 with Northwind."
In my query the Alias name - "Amount" is not being recognized. My query is as follows:
select top(5) a.customerid, sum(b.unitprice*b.quantity) as "Amount", max(c.orderdate) as Orderdate
from customers a join orders c
on a.customerid = c.customerid
join [order details] b
on c.orderid = b.orderid
group by a.customerid
--having Amount > 25000 --throws error
having sum(b.unitprice*b.quantity) > 25000 --works, but I don't think that this is a good solution
order by Orderdate desc
Pls let me know what I am doing wrong here, as I am a newbie in writing T Sql. Also can this query and my logic be treated as production level query?
TIA,
You must use the aggregate in the query you have. This all has to do with the order in which a SELECT statement is executed. The syntax of the SELECT statement is as follows:
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
The order in which a SELECT statement is executed is as follows. Since the SELECT clause isn't executed until after the HAVING clause, you can't use the alias like you can in the ORDER BY clause.
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
Reference Article: http://www.bennadel.com/blog/70-sql-query-order-of-operations.htm
This is a known limitation in SQL Server, at least, but no idea if it's a bug, intentional or even part of the standard. But the thing is, neither the WHERE or HAVING clauses accept an alias as part of their conditions, you must use only columns from the original source tables, which means that for filtering by calculated expressions, you must copy-paste the very same thing in both the SELECT and WHERE parts.
A workaround for avoiding this duplication can be to use a subquery or cte and apply the filter on the outer query, when the alias is just an "input" table:
WITH TopOrders AS (
select a.customerid, sum(b.unitprice*b.quantity) as "Amount", max(c.orderdate) as Orderdate
from customers a join orders c
on a.customerid = c.customerid
join [order details] b
on c.orderid = b.orderid
group by a.customerid
--no filter here
order by Orderdate desc
)
SELECT TOP(5) * FROM TopOrders WHERE Amount > 25000 ;
Interesting enough, the ORDER BY clause does accepts aliases directly.
You must use Where b.unitprice*b.quantity > 25000 instead of having Amount > 25000.
Having used for aggregate conditions. Your business determine your query condition. If you need to calculate sum of prices that have above value than 25000, must be use Where b.unitprice*b.quantity > 25000 and if you need to show customer that have total price above than 25000 must be use having Amount > 25000 in your query.
select top(5) a.customerid, sum(b.unitprice*b.quantity) as Amount, max(c.orderdate) as Orderdate
from customers a
JOIN orders c ON a.customerid = c.customerid
join [order details] b ON c.orderid = b.orderid
group by a.customerid
having sum(b.unitprice*b.quantity) > 25000 --works, but I don't think that this is a good solution
Order by Amount
I don't have that schema at hand, so table' and column' names might go a little astray, but the principle is the same:
select top (5) ord2.*
from (
select top (1) ord.CustomerId
from dbo.Orders ord
inner join dbo.[Order Details] od on od.OrderId = ord.OrderId
group by ord.CustomerId
having sum(od.unitPrice * od.Quantity) > $25000
) sq
inner join dbo.Orders ord2 on ord2.CustomerId = sq.CustomerId
order by ord2.OrderDate desc;
The Having Clause will works with aggregate function like SUM,MAX,AVG..
You may try like this
SELECT TOP 5 customerid,SUM(Amount)Amount , MAX(Orderdate) Orderdate
FROM
(
SELECT A.customerid, (B.unitprice * B.quantity) As "Amount", C.orderdate As Orderdate
FROM customers A JOIN orders C ON A.customerid = C.customerid
JOIN [order details] B ON C.orderid = B.orderid
) Tmp
GROUP BY customerid
HAVING SUM(Amount) > 25000
ORDER BY Orderdate DESC
The question is little ambiguos.
Show the most recent five orders that were purchased by a customer who
has spent more than $25,000 with Northwind.
Is it asking to show the 5 recent orders by all the customers who have spent more than $25,000 in all of their transactions (which can be more than 5).
The following query shows all the customers who spent $25000 in all of their transactions (not just the recent 5).
In one of the Subquery BigSpenders it gets all the Customers who spent more than $25000.
Another Subquery calculates the total amount for each order.
Then it gets rank of all the orders by OrderDate and OrderID.
Then it filters it by Top 5 orders for each customer.
--
SELECT *
FROM (SELECT C.customerid,
C.orderdate,
C.orderid,
B3.amount,
Row_number()
OVER(
partition BY C.customerid
ORDER BY C.orderdate DESC, C.orderid DESC) Rank
FROM orders C
JOIN
--Get Amount Spend Per Order
(SELECT b2.orderid,
Sum(b2.unitprice * b2.quantity) AS Amount
FROM [order details] b2
GROUP BY b2.orderid) B3
ON C.orderid = B3.orderid
JOIN
--Get Customers who spent more than 25000
(SELECT c.customerid
FROM orders c
JOIN [order details] b
ON c.orderid = b.orderid
GROUP BY c.customerid
HAVING Sum(b.unitprice * b.quantity) > 25000) BigSpenders
ON C.customerid = BigSpenders.customerid) X
WHERE X.rank <= 5

Resources