I use SQL server.
I currently have a table which contains several items, some of them have a price and some not.
However some of them have several prices columns: “Commercial price”, “Current price”, “New price”
It is possible that for some of the items not all of the 3 pricing columns above exist, and some only have “Current price” and the rest is NULL.
So I need the query to check which one of the prices columns exist/isn’t null, by the following “priority”
New price > Current price > Commercial price
(That means that if “New price” doesn’t exist or is NUll, the query will pick the price from “Current price”)
And in the end to add a row/columns which is named “Total” and calculates all the prices together.
Thanks a lot!
SELECT COALESCE([New price],[Current price],[Commercial price]) as Price
For the last part you could add a UNION with another select (possibly grouped by product or whatever), something like:
SELECT SUM(ISNULL([New Price], 0) + ISNULL([Current price], 0) + ISNULL(Commercial price], 0) AS Total
SELECT ID, SUM(ISNULL([New Price], 0) + ISNULL([Current price], 0) + ISNULL(Commercial price], 0) AS TotalPrice FROM YOURTABLE
GROUP BY ID
UNION
SELECT COUNT(ID), SUM(ISNULL([New Price], 0) + ISNULL([Current price], 0) + ISNULL(Commercial price], 0) AS TotalPrice FROM YOURTABLE
Related
I have been getting this error:
Column 'dbo.MainDB.Packaging Quantity' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This problem came up after I added the equation for Total and I have attempted to add aggregate functions to the equation, but it just gives me the wrong output if I add any. Also, if I add it to the group by clause then it adds unnecessary groups, does anyone know a solution?
Code:
SELECT
CONVERT(varchar,shipdate,101) AS Shipdate,
ID,
[Last Name],
Address,
SUM([Packaging Quantity]) AS Quantity,
Size,
SUM(Cost) AS Price,
ROUND(Size/[Packaging Quantity], 0) AS Total
FROM dbo.MainDB
WHERE
Shipdate BETWEEN '09/01/2019' AND '09/30/2019 11:59:59PM'
AND Cost <> '0'
GROUP BY
CONVERT(VARCHAR, shipdate, 101),
ID,
[First Name],
Address,
Size
The error message is clear enough.
SELECT
CONVERT(varchar,shipdate,101) AS Shipdate,
ID,
[Last Name],
Address,
SUM([Packaging Quantity]) AS Quantity, -- aggregation on [Packaging Quantity]
Size,
SUM(Cost) AS Price,
ROUND(Size/[Packaging Quantity], 0) AS Total -- no aggregation on [Packaging Quantity]
FROM ...
You need an aggregate function in the second hilighted occurence of [Packaging Quantity].Given the fact that you are SUMing the first time, it would assume that you want to aggregate the same way in the other column, so:
SELECT
CONVERT(varchar,shipdate,101) AS Shipdate,
ID,
[Last Name],
Address,
SUM([Packaging Quantity]) AS Quantity,
Size,
SUM(Cost) AS Price,
ROUND(Size/SUM([Packaging Quantity]), 0) AS Total
FROM ...
I have searched for an answer for ages with no luck for my particular problem.
I have been asked to create a script to extract data for a mail-merge. Our billing team need to identify users who we have sent final warning notices to but have still not paid their bills.
The biggest challenge that I have been unable to overcome is that some of the customers may have done one of the following:
not made any payments for the outstanding amount
paid the outstanding amount in full in one payment
paid the outstanding amount in full with multiple payments
paid part of the outstanding amount in one or multiple payments
The data that was used to generate the final warning notices is in a table with the outstanding amount appearing as a positive number, and any payments that have been made are in a different table as a negative number.
In my query identifying customers from scenario 1 and 2 would be fairly easy to identify, but 3 and 4 are causing me headaches. I had the idea of adding the outstanding amount to a sum of any payments made. If the sum total is > 0 then the customer has not paid enough to cover the outstanding amount. I have developed a sub-query to get a total of all payments made after a certain date but I can't get the query to add that to the outstanding amount and then check to see if the balance is greater than 0. Error I get is "Cannot perform an aggregate function on an expression containing an aggregate or a subquery."
Can someone recommend a different approach to this query?
SELECT
finalwarning.table_no AS [Property No],
finalwarning.value_1 AS [Arrears Balance],
finalwarning.date_1 AS [Notice Date]
FROM
finalwarning
WHERE
finalwarning.table_no = 172030
AND finalwarning.ref_3 = 'Final'
AND ((SELECT
CASE
WHEN EXISTS (SELECT 1
FROM paymentsmade
WHERE PROPERTY_NO = 1234
AND TRANSACTION_DESC = 'Receipt'
AND TRANSACTION_DATE > '2017-05-01 00:00:00.000'
GROUP BY TRANSACTION_DESC)
THEN (SELECT SUM(amount)
FROM paymentsmade
WHERE paymentsmade.PROPERTY_NO = 1234
AND paymentsmade.TRANSACTION_DESC = 'Receipt'
AND paymentsmade.TRANSACTION_DATE > '2017-05-01 00:00:00.000'
GROUP BY paymentsmade.TRANSACTION_DESC)
ELSE '0'
END) + finalwarning.value_1) < 0
CTE are our friends and really help get the hard work done for us and allow for easier writing of the core SQL. The example below takes your structure and applies the concept of a payments CTE which will aggregate payments by property no and provide for all of the calculations you need to perform in your evaluation. I was uncertain about how the date came into play and the join might be wrong because there were 2 different numbers provided for property_no in the example but I assumed they were one and the same.
WITH paymentCTE (property_no, amount, transaction_desc, cntpayments)
as
(select property_no, sum(amount) as amount, transaction_desc, count(*)
from paymentsmade
where TRANSACTION_DATE > > '2017-05-01 00:00:00.000'
group by property_no, transaction_desc
)
SELECT fw.table_no AS [Property No]
, fw.value_1 AS [Arrears Balance]
, fw.date_1 AS [Notice Date]
, coalesce(p1.amount,0) as [Payments Made]
, fw.value_1+coalesce(p1.amount,0) as [Outstanding Balance]
, coalesce(p1.cntpayments, 0) as [Number of Payments]
FROM finalwarning fw
left outer join paymentCTE p1
on fw.table_no = p1.property_no
and p1.Transaction_desc = 'Receipt'
WHERE p1.cntpayments is null
or (coalesce(p1.cntpayments, 0) = 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
or (coalesce(p1.cntpayments, 0) > 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
or (coalesce(p1.cntpayments, 0) > 0 and fw.value_1 + coalesce(p1.amount,0)<> 0)
OBJECTIVE
Develop a sales catalog for a COMPANY ID based on ITEM ID and latest PRICE paid (based on LAST SHIP DATE).
APPROACH
Pull in CUSTOMER, SALES, ITEM Tables
Run Query Link tables based off of CUSTOMER ID and ITEM to understand purchase history
Export a table showing a COMPANY ID, ITEM ID, LAST SALES PRICE, LAST SHIP DATE
CODE
SELECT
[Sales Order Details (F42119)].SDAN8 AS [COMPANY ID],
[Sales Order Details (F42119)].SDITM AS [ITEM ID],
[Sales Order Details (F42119)].SDAITM AS STYLE,
(CCur([SDLPRC])/10000) AS PRICE,
Max([Sales Order Details (F42119)].SDDRQJ) AS [LAST SHIP DATE]
INTO [Table - Sales Details]
FROM [Sales Order Details (F42119)]
GROUP BY
[Sales Order Details (F42119)].SDAN8,
[Sales Order Details (F42119)].SDITM,
[Sales Order Details (F42119)].SDAITM,
(CCur([SDLPRC])/10000);
ISSUE/QUESTION
CUSTOMER A bought ITEM ABC # 3 different prices on 3 different dates. I've taken the Max of Ship Date in hope to show the LAST PRICE PAID (resulting in one single value for price). However, for some reason, I am still receiving the three different prices on three different dates. How can I have MS Access only display the latest price based off of the latest ship date?
NOTE: SDLPRC = "Sold Price". I have to convert SLDPRC into a Currency and then divide by 1000; this is due to our current database setup. Also, SDAITM is an "Abbreviated Item Number" that is more customer-friendly.
The problem is that you're grouping by your Price variable (CCur([SDLPRC])/10000). When you use GROUP BY, Access/SQL will split the rows by all the variables in the GROUP BY statement. So you need to not group by price.
Change your query to use a subquery that finds the last date of a sale grouped by [Company ID], [Item ID] and Style. The use an outer query to grab the price for that particular record. Something like:
SELECT b.[COMPANY ID], b.[ITEM ID], b.STYLE, b.[LAST SHIP DATE], CCur(a.[SDLPRC])/10000 as PRICE
INTO [Table - Sales Details]
FROM [Sales Order Details (F42119)] as a
INNER JOIN
(SELECT
[Sales Order Details (F42119)].SDAN8 AS [COMPANY ID],
[Sales Order Details (F42119)].SDITM AS [ITEM ID],
[Sales Order Details (F42119)].SDAITM AS STYLE,
Max([Sales Order Details (F42119)].SDDRQJ) AS [LAST SHIP DATE]
FROM [Sales Order Details (F42119)]
GROUP BY
[Sales Order Details (F42119)].SDAN8,
[Sales Order Details (F42119)].SDITM,
[Sales Order Details (F42119)].SDAITM
) as b
ON a.SDAN8 = b.[COMPANY ID]
and a.SDITM = b.[ITEM ID]
and a.SDAITM = b.STYLE
and a.SDDRQJ = b.[LAST SHIP DATE]
I have 3 fields in a table, namely category, product, avg.sales. How do I calculate the percentile of each product under its respective category? Currently, I make different tables for each category and then calculate the percentile, but is it possible to do it in just one table?
Here is the code that I used. "MobilesCount" is another query which stores the total number of products in mobile category. I hope this helps
SELECT
o.CategoryID,
o.product,
o.brand,
(SELECT
COUNT(i.[Avg Sales])
FROM
[ProductItemsSold] i
WHERE
i.[Avg Sales] <= o.[Avg Sales]
AND
CategoryID = 28
AND
[Avg Sales]>0
)/(SELECT [Total Products] From MobilesCount) AS [Sales percentile]
FROM
[ProductItemsSold(Weekly)] AS o
WHERE
o.CategoryID = 28
AND
o.[Avg Sales]>0
ORDER BY
o.product;
Thanks for the help :-)
I have a query, where I need the MIN of a DateTime field and then I need the value of a corresponding field in the same row.
Now, I have something like this, however I cannot get Price field without putting it also in an aggregate clause, which is not what I want.
SELECT MIN([Registration Time]), Price FROM MyData WHERE [Product Series] = 'XXXXX'
I need the MIN of the Registration Time field and then I just want the corresponding Price field for that row, however how do I show that?
I do also need my WHERE clause as shown.
I'm sure I've overlooked something really obvious. Using SQL Server 2008
If you want just one record with [Registration Time], Price, it'd be as simple as this:
select top 1 [Registration Time], Price
from MyData
where [Product Series] = 'XXXXX'
order by [Registration Time]
If you want minimum [Registration Time] and corresponding Price for all [Product Series], then there's a few approaches, for example, using row_number() function:
with cte as (
select
[Registration Time], Price,
row_number() over(partition by [Product Series] order by [Registration Time]) as rn
from MyData
)
select
[Registration Time], Price, [Product Series]
where rn = 1