Workaround with 'Column Name is not valid' - sql-server

Hi is there any workaround with this one?
SELECT invoices.no, customers.name, invoices.mdcode,
SUM(iproducts.unitprice * iproducts.quantity) AS total,
SUM(iproducts.unitprice * iproducts.quantity) - SUM(rinvoices.payment + rinvoices.discount)
AS [Remaining Balance]
FROM invoices INNER JOIN
customers ON customers.id = invoices.customerid INNER JOIN
iproducts ON invoices.id = iproducts.invoiceid LEFT OUTER JOIN
rinvoices ON invoices.id = rinvoices.invoiceid
WHERE ([Remaining Balance] <> '0')
GROUP BY invoices.no, customers.name, invoices.mdcode
The following returns an error that '[Remaining Balance]' is not a valid column whereas i already declared it. i can't use it in both the WHERE and the CASE clauses. Is there any work around since i really need to get only the invoices that have still remaining balances.
Thanks for the help!

You have to use HAVING clause like this
HAVING SUM(rinvoices.payment) - SUM(rinvoices.discount) <> 0
instead of WHERE
Ie:
SELECT invoices.no, customers.name, invoices.mdcode,
SUM(iproducts.unitprice * iproducts.quantity) AS total,
SUM(iproducts.unitprice * iproducts.quantity) - SUM(rinvoices.payment + rinvoices.discount)
AS [Remaining Balance]
FROM invoices INNER JOIN
customers ON customers.id = invoices.customerid INNER JOIN
iproducts ON invoices.id = iproducts.invoiceid LEFT OUTER JOIN
rinvoices ON invoices.id = rinvoices.invoiceid
GROUP BY invoices.no, customers.name, invoices.mdcode
HAVING SUM(rinvoices.payment) - SUM(rinvoices.discount) <> 0

Related

SQL Server 2005 Select Data From Table1 and Table2 but if Table2 column1 value is null Select Data From Table3

My Query IS
SELECT TblPharmacyBillingDetails.UPBNo, TblMasterBillingData.IPDNo, InPatRegistration.PatTitle+PatientName, TblPharmacyBillingDetails.InvoiceNo, TblPharmacyBillingDetails.InvoiceDateTime, TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
but if TblMasterBillingData.IPDNo value is NULL select Data From TblMasterBillingData.OPDNo and
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.IPDNo
Method #1: Using UNION
SELECT * FROm
(
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.IPDNo,
InPatRegistration.PatTitle+PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
WHERE TblMasterBillingData.IPDNo IS NOT NULL
UNION ALL
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.OPDNo,
OutPatRegistration .PatTitle + PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.OPDNo
WHERE TblMasterBillingData.OPDNo IS NOT NULL
)Tmp
ORDER BY TblPharmacyBillingDetails.UPBNo
Method #2 Using ISNULL and LEFT JOIN
SELECT TblPharmacyBillingDetails.UPBNo,
ISNULL(TblMasterBillingData.IPDNo,TblMasterBillingData.OPDNo),
ISNULL(IP.PatTitle + IP.PatientName, OP.PatTitle + OP.PatientName),
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
LEFT JOIN InPatRegistration IP ON TblMasterBillingData.IPDNo = IP.IPDNo
LEFT JOIN outPatRegistration OP ON TblMasterBillingData.OPDNo = OP.OPDNo
ORDER BY TblPharmacyBillingDetails.UPBNo
You can write either case statement or ISNULL() function as shown below in the demo query.
SELECT
Orders.OrderID,
Case when Customers1.CustomerName is null then Customers2.CustomerName else Customers1.CustomerName
end as CustomerName, --way 1
ISNULL(Customers1.CustomerName, Customers2.CustomerName) as Customer, --way 2
Orders.OrderDate
FROM Orders
INNER JOIN Customers1 ON Orders.CustomerID = Customers1.CustomerID
INNER JOIN Customers2 ON Orders.CustomerID = Customers2.CustomerID
-- where your condition here
-- order by your column name
You can also check whether data is available or not in the table and join the table accordingly using if exists as shown below.
if exists(select 1 from tablename where columnname = <your values>)

How to break sales query results by day

I have a sales query by date range, where the date range is defined by user input. I would like to divide the results by day. i.e.: say the user input the date range from 01/01/16 - 01/15/16, I would like the break the results for each day.
I'm using DATENAME(DD,T1.[DocDate]) to break it, and it is kind of working, but the results are no accurate. I figure I have to use the same break in the Returns subquery. Please see the full query below:
Thank you
SELECT
'2016' as 'Year',
t4.remarks as 'Department',
DATENAME(DD,T1.[DocDate]) as 'Day',
sum(t0.[quantity])-(ISNULL(p.quantity,0)) as 'Quantity',
sum(t0.linetotal - t0.linetotal*t1.discprcnt/100)-(ISNULL(p.total,0)) as 'Total',
sum(T0.[GrssProfit])-(ISNULL(p.profit,0)) as 'Profit $',
(sum(T0.[GrssProfit])-(ISNULL(p.profit,0)))/(sum(t0.linetotal - t0.linetotal*t1.discprcnt/100)-(ISNULL(p.total,0)))*100 as 'Profit%'
FROM INV1 T0 with (nolock)
INNER JOIN OINV T1 with (nolock) on t0.docentry = t1.docnum
INNER JOIN OSLP T2 with (nolock) on t0.SlpCode = t2.SlpCode
LEFT JOIN OHEM T3 with (nolock) on t0.slpcode = t3.SalesPrson
LEFT JOIN OUDP T4 with (nolock) on t3.dept = t4.Code
--BEGINS QUERY FOR THE RETURNS--
left join (select t9.name as 'dept',sum(t5.quantity) as 'quantity',sum(t5.linetotal - t5.linetotal*t6.discprcnt/100) as 'total',sum(t5.grssprofit) as 'profit'
from [dbo].[rin1] t5 with (nolock)
inner join orin t6 with (nolock) on t5.docentry = t6.docentry
INNER JOIN OSLP T7 with (nolock) on t5.SlpCode = t7.SlpCode
LEFT JOIN OHEM T8 with (nolock) on t5.slpcode = t8.SalesPrson
LEFT JOIN OUDP T9 with (nolock) on t8.dept = t9.Code
INNER JOIN OITM T10 with (nolock) on t5.itemcode = t10.itemcode
where t5.docdate between '[%1]' and '[%2]' and t10.invntitem = 'Y'
and (t5.linetotal - (t5.linetotal*t6.discprcnt/100)) <> '0'
group by t9.name) p on p.dept = t4.name
--ENDS QUERY FOR THE RETURNS--
WHERE t1.docdate between '[%1]' and '[%2]'
and t4.remarks is not null
and t4.remarks = 'perfume provider'
and (t0.linetotal - (t0.linetotal*t1.discprcnt/100)) <> '0'
group by DATENAME(DD,T1.[DocDate]),t4.remarks,p.quantity,p.total,p.profit
Instead of a sub-query for your returns (with the same kind of group by as your Invoices query), you should use a UNION instead. Your Group-By is fine, but like you mentioned, your subquery is going to result in bad data.
Any time you have distinct "starting points" for your data, a Union is the way to go.

Group nested selected query returning all rows

I'm trying to display the data so that only one line is displayed per customer, i'm having trouble with trying to achieve that with my code as its returning all records, can anyone help
SELECT customerOrdrs.NAME AS 'Name',
customerOrdrs.currentbalance -
Sum(COALESCE(customerOrdrs.revisedbalance, 0)) AS 'RevisedBalance',
sold AS 'NumberOfItemsSold'
FROM customers,
(SELECT c.NAME AS NAME,
c.balance AS CurrentBalance,
i.qty AS RevisedBalance,
( Min(s.price) * i.qty ) AS Sold
FROM customers c
INNER JOIN sales o
ON c.NAME = o.custname
INNER JOIN purchases i
ON i.orderno = o.orderno
INNER JOIN contracters s
ON i.item = s.item
GROUP BY c.NAME,
c.balance,
i.qty) customerOrdrs
GROUP BY customerOrdrs.NAME,
customerOrdrs.currentbalance,
sold
I'm not sure how your data looks but I have reformatted the query and there are a few things I've noticed off the bat.
I have removed the subquery as I don't believe it is necessary - in addition your original query is referring to customer table twice without defining a join
Select [C].[Name] As [Name]
, [CurrentBalance] = [C].[Balance]
, [RevisedBalance] = [C].[Balance] - Sum([P].[Qty])
, [Sold] = ( Min([CO].[Price]) * sum([P].[Qty]) )
From [CUSTOMERS] [C]
Inner Join [Sales] [s]
On [C].[Name] = [s].[custName]
Inner Join [Purchases] [P]
On [P].[OrderNo] = [s].[OrderNo]
Inner Join [Contracters] [CO]
On [P].[Item] = [CO].[Item]
Group By [C].[Name]
, [C].[Balance];

Use a calculated column in a where clause

I'm trying to use a calculated column in a where clause.
I've trying everything from CROSS APPLY, to sub-query select but it does not give me the anything near what I need.
My query so far:
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
WHERE Sales > 100
GROUP BY p.Code, c.AccountNumber, Sales
This does not work, as 'Sales' is an invalid column
Using Derived Columns in a predicate
You'll need to wrap the inner query in a derived table or CTE in order to be able to use derived columns in the WHERE clause (Also, note SUM() is specified just once, using the results of the multiplication):
SELECT x.Code, x.AccountNumber, x.Sales
FROM
(
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
) AS x
WHERE x.Sales > 100;
Repeating the Derived Column in a HAVING clause
As per #Jonny's comment, the other way is not to DRY up the calculated column, but to instead repeat the calculation. Use HAVING instead of WHERE after a GROUP BY has been applied.
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
HAVING SUM(p.UnitPrice * od.QtyShipped) > 100;
In either case, as per comments below, note that the calculated expression is SUM(p.UnitPrice * od.QtyShipped) and not SUM(p.UnitPrice) * SUM(od.QtyShipped).
You can use the common table expression for this
;WITH CTE AS
(
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber, Sale
)
SELECT *
FROM CTE WHERE CTE.Sales>100
If it's a calculated column you can use "HAVING".
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber, Sales
HAVING SALES > 100;

Get distinct rows when filtering and using dynamic order by

My first version of the question was confusing, I need to make smaller chunks.
If a user can filter products from a website, one product should occur only once in the list.
Because of joins this code gives me two same products, how do I solve that?
I think I need a solution without using distinct because it will give me headache later on.
code from AW2012:
declare #safetystocklevel int
set #safetystocklevel = 1000
declare #status int
set #status = 2
select * from Production.Product p
inner join Purchasing.ProductVendor pv on p.ProductID = pv.ProductID
inner join Purchasing.Vendor v on v.BusinessEntityID = pv.BusinessEntityID
inner join Production.ProductDocument pd on p.ProductID = pd.ProductID
inner join Production.Document d on d.DocumentNode = pd.DocumentNode
WHERE
(#safetystocklevel = '' or p.SafetyStockLevel = #safetystocklevel)
and (#status = '' or d.Status = #status)
output:
ProductId Name
506 Reflector
506 Reflector
Edit:
Thanks, I now use Group by to get distinct rows.
Yeah, maybe using group by works for me, Im gonna do some testing now.....
Hi again
I want all products to be searchable, so I guess I need left outer joins to achieve that.
When I add dynamic order by I get into trouble, more rows are added.
Probably because I must add poh.Status to the group by.
There are 504 rows in the product table, this query returns 776 rows.
(I have removed the filtering in WHERE since it is not interesting now, and Im joining to other tables now just to get more rows to play with)
Code:
declare #sortType nvarchar(50)
set #sortType = 'Status'
select p.ProductID,
CASE WHEN #sortType = 'Status' THEN poh.Status END as Status,
CASE WHEN #sortType = 'ProductId' THEN p.ProductID END as ProductId
from Production.Product p
left outer join Purchasing.PurchaseOrderDetail pod on p.ProductID = pod.ProductID
left outer join Purchasing.PurchaseOrderHeader poh on poh.PurchaseOrderID = pod.PurchaseOrderID
left outer join Production.ProductDocument ppd on ppd.ProductID = p.ProductID
left outer join Production.Document pd on pd.DocumentNode = ppd.DocumentNode
group by p.ProductID, poh.Status
ORDER BY
CASE WHEN #sortType = 'Status' THEN poh.Status END ASC,
CASE WHEN #sortType = 'ProductId' THEN p.ProductID END ASC
You can use Group By ProductId, Name, to select the single row, if you are not planning to include distinct. But I'll prefer "distinct" if you are not using any aggregate value in select clause.
select p.ProductId, p.Name from Production.Product p
inner join Purchasing.ProductVendor pv on p.ProductID = pv.ProductID
inner join Purchasing.Vendor v on v.BusinessEntityID = pv.BusinessEntityID
inner join Production.ProductDocument pd on p.ProductID = pd.ProductID
inner join Production.Document d on d.DocumentNode = pd.DocumentNode
WHERE
(#safetystocklevel = '' or p.SafetyStockLevel = #safetystocklevel)
and (#status = '' or d.Status = #status)
GROUP BY p.ProductId, p.Name

Resources