How does a sub query in the from clause work? - sql

What is a valid use-case for Sub Query in the FROM clause? How does that scheme work? There are many examples of this type in SO. A link to one of those is here but I can't see how this scheme works.
P.S: If the answer is Oracle specific it is fine.

Here are some use cases for a subquery in the from clause. How it works has been explained in the comments to your question (SQL is mathematical closed thanks to its relational operators).
1. Pivot (SQL Server 2008)
select P.RUN_ID
, [2012] = sum(P.[2012])
, [2013] = sum(P.[2013])
, [2014] = sum(P.[2014])
, [2015] = sum(P.[2015])
from (select T.RUN_ID
, Y.YEAR
, T.MEASURE
from SOME_TABLE T
inner join
YEAR Y
on T.SOME_ID = Y.SOME_ID
) T
pivot (
sum(MEASURE)
for YEAR in ([2012], [2013], [2014], [2015])
) P
group by
P.RUN_ID
order by
P.RUN_ID
2. over clause (Oracle) based on a union
select S.Text_ID
, row_number() over (partition by S.Text_ID order by S.Segmentstart) as Segmentnumber
, S.Segment_ID
, S.Segmentstart
, S.Segmentend
, S.Segmentfragment
from (select S.Text_ID as Text_ID
, S.Satz_ID as Segment_ID
, S.Start as Segmentstart
, S.End as Segmentend
, S.Fragment as Segmentfragment
from Mainclauses S
union all
select X.ID as Text_ID
, null as Segment_ID
, coalesce(S.End, 0) as Segmentstart
, lead(S.Start, 1, X.CONTENT_LENGTH) over (partition by X.ID order by S.Start) as Segmentend
, 'X' as Segmentfragment
from Texts X
left join
Mainclauses S
on X.ID = S.Text_ID
union all
select X.ID as Text_ID
, null as Segment_ID
, 0 as Segmentstart
, min(S.Start) as Segmentend
, 'X' as Segmentfragment
from Texts X
inner join
Mainclauses S
on X.ID = S.Text_ID
group by
X.ID
) S
3. over clause (SQL Server 2008) with join and aggregate
select E.X_ID
, Z.SomeThing
, sum(Z.OtherMeasure * E.Measure) as CombinedMeasure
, Sorting = row_number() over
( partition by
E.X_ID
order by
Z.SomeThing
)
from (select E.X_ID
, E.Y_ID
, Measure = sum(E.Measure)
from SomeTable E
group by
E.X_ID
, E.Y_ID
) E
inner join
OtherTable Z
on E.Y_ID = Z.Y_ID
4. Calculate ratio (SQL Server 2008)
with SomeData
( Main_ID
, Sub_ID
, Measure
)
as (select Main_ID
, Sub_ID
, Measure = sum(Measure)
from SomeTable P
group by
Main_ID
, Sub_ID
)
select Main_ID
, Sub_ID
, Ratio = D.Measure / sum(M.Measure) over (partition by M.Main_ID)
from SomeData D
inner join
(select Main_ID
, Measure = sum(Measure)
from SomeData
group by
Main_ID
having sum(Measure) != 0
) M
on M.Main_ID = D.Main_ID
5. Partial Comparision of two (or more) tables (SQL Server 2008)
select *
from (select A, M = sum(M) from S group by A) X
full outer join
(select A, M = sum(M) from T group by A) Y
on X.A = Y.A
where X.A is null
or Y.A is null
or abs(X.M - Y.M) > 0.00000001
Note: These are examples only and in I thought that the subquery in the from clause have been a good solution to achieve the result.

Related

Use CTE in SQL to flag DUPLICATES and reference in sub-query

So I have the following CTE:
with dupeinv AS (
select * from (
select
tci.t_idoc,
tci.t_idat,
ROW_NUMBER() OVER (partition by tci.t_idoc ORDER BY tci.t_idoc, tci.t_idat DESC) as rn
from [ln106].[dbo].tcisli305100 tci
) as t
where t.rn = 1
)
There are duplicates in the above table ([ln106].[dbo].tcisli305100) , hence the CTE to get single values. I want to format just these values in the below query (prefixed with ---)
select 'JCI' as BU,
RTRIM(LTRIM(cl.t_orno)) AS SALES_ORDER_NUMBER
, cl.t_pono AS SALES_ORDER_LINE_NUMBER
, CONCAT(cl.t_shpm, cl.t_pono, cl.t_idoc) AS SHIPPING_RECORD_ID
,CASE WHEN cl.t_dqua = 0 or cl.t_dqua is null THEN cl.t_amti ELSE
cl.t_amti / cl.t_dqua END AS AR_INVOICE_LINE_ITEM_PRICE_LOCAL
, cl.t_line AS AR_INVOICE_LINE_NUMBER
, cl.t_dqua AS AR_INVOICE_LINE_ITEM_QUANTITY
--- , concat(dupeinv.t_idoc,'|',format(dupeinv.t_idat,'MMddyyyy') ---
,ci.t_ccur AS AR_INVOICE_CURRENCY
, ci.t_idat AS AR_INVOICE_DATE
FROM [ln106].[dbo].tcisli310100 cl
LEFT JOIN [ln106].[dbo].tcisli305100 ci ON cl.t_idoc = ci.t_idoc
LEFT JOIN t di on cl.t_doc = di_t_doc
LEFT JOIN (SELECT t_orno,t_pono FROM [ln106].[dbo].ttdsls401100 WHERE t_oltp <> 1 group by t_orno,t_pono) as l --Jed 10162020 Changed the join to prevent duplicate records
ON l.t_orno=cl.t_orno COLLATE SQL_Latin1_General_CP1_CI_AS AND l.t_pono=cl.t_pono
LEFT JOIN dupeinv tci on cl.r_idoc = ci.t_doc
WHERE ci.t_idat > '2017'
Query doesn't like me referencing it in the main query. Can anyone help, or suggest a better idea?
Your final query should look something like this:
WITH dupeinv AS
(SELECT *
FROM
(SELECT tci.t_idoc,
tci.t_idat,
ROW_NUMBER() OVER (PARTITION BY tci.t_idoc
ORDER BY tci.t_idoc,
tci.t_idat DESC) AS rn
FROM [ln106].[dbo].tcisli305100 tci) AS t
WHERE t.rn = 1 )
SELECT 'JCI' AS BU,
RTRIM(LTRIM(cl.t_orno)) AS SALES_ORDER_NUMBER ,
cl.t_pono AS SALES_ORDER_LINE_NUMBER ,
CONCAT(cl.t_shpm, cl.t_pono, cl.t_idoc) AS SHIPPING_RECORD_ID ,
CASE
WHEN cl.t_dqua = 0
OR cl.t_dqua IS NULL THEN cl.t_amti
ELSE cl.t_amti / cl.t_dqua
END AS AR_INVOICE_LINE_ITEM_PRICE_LOCAL ,
cl.t_line AS AR_INVOICE_LINE_NUMBER ,
cl.t_dqua AS AR_INVOICE_LINE_ITEM_QUANTITY ,
concat(dupeinv.t_idoc,
'|',
format(dupeinv.t_idat, 'MMddyyyy')) ,
ci.t_ccur AS AR_INVOICE_CURRENCY ,
ci.t_idat AS AR_INVOICE_DATE
FROM [ln106].[dbo].tcisli310100 cl
LEFT JOIN [ln106].[dbo].tcisli305100 ci ON cl.t_idoc = ci.t_idoc
LEFT JOIN t di ON cl.t_doc = di_t_doc
LEFT JOIN
(SELECT t_orno,
t_pono
FROM [ln106].[dbo].ttdsls401100
WHERE t_oltp <> 1
GROUP BY t_orno,
t_pono) AS l --Jed 10162020 Changed the join to prevent duplicate records
ON l.t_orno=cl.t_orno COLLATE SQL_Latin1_General_CP1_CI_AS
AND l.t_pono=cl.t_pono
LEFT JOIN dupeinv tci ON cl.r_idoc = ci.t_doc
WHERE ci.t_idat > '2017'

How to get biggest value from 2 or more fields in a subquery

I have a table with customers that I join with a fact table with sales, based on invoices.
What I need from my report is to get in first part the biggest value of sales based on the incoming order type (1,2,3,C,D) for a customer for last year. And in the second part to get the same but for current year. What I get as result from my current query is all incoming order types with the customer revenue made for each of them. I tried with outer apply as subquery to get only the top 1 value ordered by revenue descending, but in the result I get the same - For all order types the customer revenue. Please help! I hope my explanation isn't understood only by me (happens a lot..)
use dwh01;
WITH OrderTypeUsedLY AS
(
SELECT
c.CustomerKey
,c.BranchId
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_LY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_LY]
,y.IncomingOrderTypeId as IncomingOrderType_LY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE())-1 --- Last Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId
),
--*********************************************************************************************************************************--
OrderTypeCY as(
SELECT
c.CustomerKey
,c.BranchId
,c.SalesRepKey
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_CY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_CY]
,y.IncomingOrderTypeId as IncomingOrderType_CY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE()) --- Current Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId, c.SalesRepKey
)
--*********************************************************************************************************************************--
SELECT
otly.BranchId,
rep.SalesRepId,
rep.SalesRepName,
otly.CustomerId,
otly.CustomerName,
otly.Sale_Revenue_LY,
otly.Sale_GrossMarginTotal_LY,
IncomingOrderType_LY,
otcy.Sale_Revenue_CY,
otcy.Sale_GrossMarginTotal_CY,
IncomingOrderType_CY
from OrderTypeUsedLY otly
left join OrderTypeCY otcy
on otly.CustomerKey = otcy.CustomerKey
join live.DimCustomer cus on cus.CustomerKey = otcy.CustomerKey
join live.DimSalesRep rep on rep.SalesRepKey = otcy.SalesRepKey
order by otcy.Sale_Revenue_CY desc, otly.Sale_Revenue_LY desc
,rep.SalesRepId
And here is the outer apply I tried:
outer apply (
SELECT top 1
iot.IncomingOrderTypeId,
Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
where iot.IncomingOrderTypeKey = y.IncomingOrderTypeKey
order by Sale_Revenue desc) x
In the first select ( with OrderTypeUsed_LY ) I get this:
And I get the same in the second select, but with the values for current year.
The purpose of the report is to see the difference in the incoming order type most used (most profit made with it) for a customer last year and to see if he continues to use it this year, or uses another incoming order type this year.
Again I'm sorry for the bad explanation, I'm trying my best (I understand myself very well)
Here is the expected result:
Expected Result
I marked in red the last year part and in green the current year part.
If you change the subquery to:
SELECT
iot.IncomingOrderTypeKey,
MAX(Sale_Revenue)
FROM [dwh01].[live].DimIncomingOrderType iot
GROUP BY iot.IncomingOrderTypeKey
then you can JOIN (not APPLY) directly on IncomingOrderTypeKey AND Sale_Revenue.
Try this:
USE dwh01;
DECLARE #CustomerKey varchar(6) = '157053'
, #ReportCurrencyId varchar(2) = 'LC'
, #CurrentYear int = YEAR(GETDATE())
, #TargetYear int = YEAR(GETDATE())-1
;
WITH FactsTable AS
(
SELECT
s.CustomerKey
, i.IncomingOrderTypeid
, [Sale_Revenue] = ISNULL(s.[Sale_Revenue] , 0)
, [Sale_GrossMarginTotal] = ISNULL(s.[Sale_GrossMarginTotal], 0)
, d.[Year]
FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType i on i.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where
s.CustomerKey = #CustomerKey
and s.ReportCurrencyId = #ReportCurrencyId
)
, OrderTypeTable
(
SELECT
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, c.SalesRepKey
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
FROM live.DimCustomer c
left join FactsTable y on y.CustomerKey = c.CustomerKey
group by
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, y.IncomingOrderTypeId
, c.SalesRepKey
)
SELECT
O.BranchId
, R.SalesRepId
, R.SalesRepName
, O.CustomerId
, O.CustomerName
, O.Sale_Revenue_LY
, O.Sale_GrossMarginTotal_LY
, O.IncomingOrderType_LY
, O.Sale_Revenue_CY
, O..Sale_GrossMarginTotal_CY
, O.IncomingOrderType_CY
from OrderTypeTable O
join live.DimSalesRep R on R.SalesRepKey = O.SalesRepKey
order by
O.Sale_Revenue_CY desc
, O.Sale_Revenue_LY desc
, R.SalesRepId
The solution is with using row_number() function in the inner query of the first CTE:
(
select *, row_number() over (partition by x0.CustomerKey order by x0.Sale_Revenue desc) as rn
from
(
select fs.CustomerKey, iot.IncomingOrderTypeKey,
sum(fs.Sale_Revenue) as Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
join live.FactSales fs
on iot.IncomingOrderTypeKey = fs.IncomingOrderTypeKey
join live.DimDate d
on d.DateId = fs.PostingDateKey
where d.[year] = #CurrentYear
GROUP BY fs.CustomerKey, iot.IncomingOrderTypeKey
) as x0
) as x1 on x1.CustomerKey = s.CustomerKey
The row_number() function gets only the first row from the result for each customer, and that is with the biggest sale revenue ( order by sale_revenue desc).

Ways to avoid "This type of correlated subquery pattern is not supported"

This is what I'm trying to do
select something1,something2,account_id,
(select u.organization_id
from public.sfdc_contact sfdcc
join public.users u on u.email=sfdcc.email
where sfdcc.account_id=account_id
group by u.organization_id
order by count(*)
limit 1
)
from something
Redshift prompted me the error because I was trying to ORDER BY count. But I can't have 2 columns in a subquery, any tips?
Not entirely sure if this structure will exactly meet your needs, but using "window functions" such as ROW_NUMBER() OVER() can be used to supply single rows from joined derived tables (subqueries). For example:
SELECT
s.something1
, s.something2
, s.account_id
, d2.organization_id
, d2.cn
FROM something s
LEFT JOIN (
SELECT
organization_id
, account_id
, cn
, ROW_NUMBER() OVER (PARTITION BY organization_id ORDER BY cn) rn
FROM (
SELECT
u.organization_id
, sfdcc.account_id
, COUNT(*) OVER (PARTITION BY u.organization_id, sfdcc.account_id) cn
FROM public.sfdc_contact sfdcc
JOIN public.users u ON u.email = sfdcc.email
) d1
) d2 ON s.account_id = d2.account_id and d2.rn = 1
The use of COUNT() OVER() is probably unnecessary and this may be more pragmatic:
SELECT
s.something1
, s.something2
, s.account_id
, d2.organization_id
, d2.cn
FROM something s
LEFT JOIN (
SELECT
organization_id
, account_id
, cn
, ROW_NUMBER() OVER (PARTITION BY organization_id ORDER BY cn) rn
FROM (
SELECT
u.organization_id
, sfdcc.account_id
, COUNT(*) cn
FROM public.sfdc_contact sfdcc
JOIN public.users u ON u.email = sfdcc.email
GROUP BY
u.organization_id
, sfdcc.account_id
) d1
) d2 ON s.account_id = d2.account_id and d2.rn = 1
Note also that if you wanted the HIGHEST count then change the order used in the row_number to DESCending:
, ROW_NUMBER() OVER (PARTITION BY organization_id ORDER BY cn DESC) rn

Get Distinct results of all columns based on MAX DATE of one

Using SQL Server 2012
I have seen a few threads about this topic but I can't find one that involves multiple joins in the query. I can't create a VIEW on this database so the joins are needed.
The Query
SELECT
p.Price
,s.Type
,s.Symbol
, MAX(d.Date) Maxed
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON
p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
The query works but does not produce distinct results. I am using Order by to validate the results, but it is not required once I get it working. I The result set looks like this.
Price Type Symbol Maxed
10.57 bfus *bbkd 3/31/1989
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
100.8161 cbus 001397AA6 7/21/2005
The result set I want is
Price Type Symbol Maxed
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
Here were a few other StackOverflow threads I tried but couldn't get t work with my specific query
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Selecting distinct rows from multiple columns based on max value in one column
If you want data for the maximum date, use row_number() rather than group by:
SELECT ts.*
FROM (SELECT p.Price, s.Type, s.Symbol, d.Date,
ROW_NUMBER() OVER (PARTITION BY s.Type, s.Symbol
ORDER BY d.Date DESC
) as seqnum
FROM AdventDW.dbo.FactPrices p INNER JOIN
dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID INNER JOIN
dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
) ts
WHERE seqnum = 1
ORDER BY s.Symbol;
You should use a derived table since you really only want to group the DateTimeKey table to get the MAX date.
SELECT p.Price ,
s.Type ,
s.Symbol ,
tmp.MaxDate
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s ON s.SecurityID = p.SecurityID
INNER JOIN
( SELECT MAX(d.Date) AS MaxDate ,
d.DateTimeKey
FROM dbo.DimDateTime d
GROUP BY d.DateTimeKey ) tmp ON p.DateTimeKey = tmp.DateTimeKey
ORDER BY s.Symbol;
/*
this is your initial select which is fine because this is base from your original criteria,
I cannot ignore this so i'll keep this in-tact. Instead from here i'll create a temp
*/
SELECT
p.Price
, s.Type
, s.Symbol
, MAX(d.Date) Maxed
INTO #tmpT
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
SELECT innerTable.Price, innerTable.Symbol, innerTable.Type, innerTable.Maxed
FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY t1.Symbol, t1.Type, t1.Maxed ORDER BY t1.Maxed DESC) as row
, *
FROM #tmpT AS t1
) AS innerTable
WHERE row = 1
DROP TABLE #tmpT

group by function with complicated SELECT

Hi
I have this Statement that select a sum of quantity ans Amounts of products from a big DataBase
SELECT
(SELECT Name FROM AD_Org WHERE AD_Org_ID = 1000001
) AS Org,
(SELECT bp.Name FROM C_BPartner bp WHERE bp.C_BPARTNER_ID = 0
) AS Selected_Vendor,
(SELECT MAX(bp.Name)
FROM C_BPartner bp
WHERE EXISTS
(SELECT 1
FROM M_Product_PO po
WHERE bp.C_BPARTNER_ID =po.C_BPARTNER_ID
AND po.M_PRODUCT_ID = p.M_PRODUCT_ID
AND po.ISCURRENTVENDOR ='Y'
AND AD_Org_ID = 1000001
)
) AS Vendor,
p.Value AS Value_Product,
p.Name AS Name_Product,
COALESCE( SUM(ol.QTYORDERED) , 0) AS qty_bought ,
COALESCE( SUM(ol.LINENETAMT) , 0) AS Amount_bought ,
COALESCE( SUM(ol2.QTYORDERED) , 0) AS qty_sales ,
COALESCE( SUM(ol2.LINENETAMT) , 0) AS Amount_sales,
bomOffQtyOnHand(p.M_PRODUCT_ID,
(SELECT NVL(M_WAREHOUSE_ID,0) FROM AD_OrgInfo WHERE AD_Org_ID = 1000001
), NULL) AS STOCK,
(SELECT Name FROM M_PRODUCT_CATEGORY pc WHERE pc.M_PRODUCT_CATEGORY_ID =0
) AS Product_Category
FROM M_Product p
LEFT OUTER JOIN C_OrderLine ol
ON (p.m_product_id = ol.m_product_id)
INNER JOIN C_Order o
....
....
WHERE (p.M_PRODUCT_CATEGORY_ID =0
....
....
)
ORDER BY p.value,
p.Nam
this statement give me always group function error
ORA-00937: not a single-group group function
when i Put this lines to fix it it give another group by error
GROUP BY SUM(ol.QTYORDERED) ,
SUM(ol.LINENETAMT),
SUM(ol2.QTYORDERED),
SUM(ol2.LINENETAMT),
p.Value,
p.name
error
ORA-00934: group function is not allowed here
I think I must put All the selected items in the group by so how can I put this
(SELECT Name FROM AD_Org WHERE AD_Org_ID = 1000001
) AS Org,
or this
(SELECT MAX(bp.Name)
FROM C_BPartner bp
WHERE EXISTS
(SELECT 1
FROM M_Product_PO po
WHERE
....
AND AD_Org_ID = 1000001
)
) AS Vendor,
in the group by or any other method to fix this error
You aggregate with SUM here:
COALESCE( SUM(ol.QTYORDERED) , 0) AS qty_bought ,
COALESCE( SUM(ol.LINENETAMT) , 0) AS Amount_bought ,
COALESCE( SUM(ol2.QTYORDERED) , 0) AS qty_sales ,
COALESCE( SUM(ol2.LINENETAMT) , 0) AS Amount_sales,
So everything else (p.Value, p.Name, p.M_PRODUCT_ID) must be either in the GROUP BY clause or be aggregated, too ( e.g. MIN(p.Value) ).