SQL into LINQ... need a nudge in the right direction - sql

I want to use LINQ as a DataGrivdView Datasource... I have the correct SQL query, but I'm having a heck of a time re-writing it in LINQ...
SQL:
SELECT ICITEM.ITEMNO, ICITEM.[DESC], MAX(PORCPL.DTARRIVAL) AS Expr1
FROM ICITEM INNER JOIN
PORCPL ON PORCPL.ITEMNO = ICITEM.ITEMNO
WHERE (ICITEM.ITEMNO LIKE '%R001%')
GROUP BY ICITEM.ITEMNO, ICITEM.[DESC]
My feeble attempt(s) at LINQ:
Dim s = From items In db.ICITEMs
Where items.ITEMNO.Contains(Me.txtQuery.Text) Or items.DESC.Contains(Me.txtQuery.Text)
Join recDates In db.PORCPLs On items.ITEMNO Equals recDates.ITEMNO
Select [Item_ID] = items.ITEMNO, [Description] = items.DESC, [rd] = recDates.DTARRIVAL
My LINQ Log...
SELECT [t0].[ITEMNO] AS [Item_ID], [t0].[DESC] AS [Description], [t1].[DTARRIVAL] AS [rd]
FROM [dbo].[ICITEM] AS [t0]
INNER JOIN [dbo].[PORCPL] AS [t1] ON [t0].[ITEMNO] = [t1].[ITEMNO]
WHERE ([t0].[ITEMNO] LIKE #p0) OR ([t0].[DESC] LIKE #p1)
-- #p0: Input VarChar (Size = 8000; Prec = 0; Scale = 0) [%r001%]
-- #p1: Input VarChar (Size = 8000; Prec = 0; Scale = 0) [%r001%]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
I can't figure out how to get a Max function on the [rd] field... ANY insight would be most appreciated.

You need to add a Group By.
Here is an example which should help:
Dim s = From items In db.ICITEMs
Where items.ITEMNO.Contains(Me.txtQuery.Text) Or items.DESC.Contains(Me.txtQuery.Text)
Join recDates In db.PORCPLs On items.ITEMNO Equals recDates.ITEMNO
Group By items.ITEMNO, items.DESC Into MaxArrivalDate = Max(recDates.DTARRIVAL)
Select [Item_ID] = items.ITEMNO, [Description] = items.DESC, [rd] = MaxArrivalDate

You have an additional Contains in your linq query. If this is correct, here is the full linq query with group by and max:
Dim s = From items In db.ICITEMs
Where items.ITEMNO.Contains(Me.txtQuery.Text) Or items.DESC.Contains(Me.txtQuery.Text)
Join recDates In db.PORCPLs On items.ITEMNO Equals recDates.ITEMNO
Group By items.ITEMNO, items.DESC Into Group
Let MaxArrival = Group.Max(Function(p) p.recDates.DTARRIVAL)
Select [Item_ID] = ITEMNO, [Description] = DESC, [rd] = MaxArrival

Related

'Order By' with 'Union' and 'GroupBy' (Oracle)

Good Morning. I have a query that has Group By and Union tables. The problem is when I try to order the final result. I'm always getting an error:
SELECT {Account}.[Id], {Account}.[AccountName], {Account}.[Project], {Account}.[Initiative], {Account}.[AccountName], {Application}.[Id], {Application}.[ApplicationName]
FROM {Account}
INNER JOIN {ApprovalWorkUnitDetail} ON {ApprovalWorkUnitDetail}.[AccountID] = {Account}.[Id]
INNER JOIN {Issue} ON {Issue}.[Id] = {ApprovalWorkUnitDetail}.[IssueID]
INNER JOIN {ServiceRequest} ON {ServiceRequest}.[Id] = {Issue}.[ServiceRequestId]
INNER JOIN {ServiceRequestProduct} ON {ServiceRequestProduct}.[ServiceRequestId] = {ServiceRequest}.[Id]
INNER JOIN {Product} ON {Product}.[Id] = {ServiceRequestProduct}.[ProductId]
LEFT JOIN {Application} ON {Application}.[Id] = {Account}.[ApplicationID]
WHERE ({ApprovalWorkUnitDetail}.[ContractID] = #ContractID)
AND ({ServiceRequest}.[Id] = #ServiceRequestID OR #ServiceRequestID = #NullIdentifier)
AND ({Product}.[Id] = #ProductID OR #ProductID = #NullIdentifier)
AND ({ApprovalWorkUnitDetail}.[MonthIdentifier] = #MonthIdentifier)
AND ({ApprovalWorkUnitDetail}.[YearIdentifier] = #YearIdentifier)
AND ({Issue}.[PaymentStatusID] = #PaymentStatusApprovedID)
UNION
SELECT {Account}.[Id], {Account}.[AccountName], {Account}.[Project], {Account}.[Initiative], {Account}.[AccountName], {Application}.[Id], {Application}.[ApplicationName]
FROM {Account}
INNER JOIN {ApprovalRefinementDetail} ON {ApprovalRefinementDetail}.[AccountID] = {Account}.[Id]
INNER JOIN {Worklog} ON {Worklog}.[Id] = {ApprovalRefinementDetail}.[WorklogID]
INNER JOIN {Issue} ON {Worklog}.[IssueId] = {Issue}.[Id]
INNER JOIN {ServiceRequest} ON {ServiceRequest}.[Id] = {Issue}.[ServiceRequestId]
INNER JOIN {ServiceRequestProduct} ON {ServiceRequestProduct}.[ServiceRequestId] = {ServiceRequest}.[Id]
INNER JOIN {Product} ON {Product}.[Id] = {ServiceRequestProduct}.[ProductId]
LEFT JOIN {Application} ON {Application}.[Id] = {Account}.[ApplicationID]
WHERE ({ApprovalRefinementDetail}.[ContractID] = #ContractID)
AND ({Product}.[Id] = #ProductID OR #ProductID = #NullIdentifier)
AND ({ServiceRequest}.[Id] = #ServiceRequestID OR #ServiceRequestID = #NullIdentifier)
AND ({ApprovalRefinementDetail}.[MonthIdentifier] = #MonthIdentifier)
AND ({ApprovalRefinementDetail}.[YearIdentifier] = #YearIdentifier)
AND ({Worklog}.[PaymentStatusID] = #PaymentStatusApprovedID)
GROUP BY {Account}.[Id], {Account}.[AccountName], {Account}.[Project], {Account}.[Initiative], {Account}.[AccountName], {Application}.[Id], {Application}.[ApplicationName]
ORDER BY {Account}.[AccountName]
I don't know why I am always getting error ORA-00904 and it indicates that AccountName is an invalid identifier.
I am using ORACLE database.
Many thanks
I would recommend moving your union query to a subquery, and sorting in the outer scope:
select *
from (
-- your big query
) t
order by accountname

Total the results of a subquery in group by

I have a query that produces the detailed data I need.
Now I need to change the results to produce a single total by dbo.Contract.Description and dbo.PMTask.Description instead of the individual entries that would comprise the total.
Here's what I have that works:
SELECT dbo.Contract.Description, dbo.PMTask.Description,
CAST(dbo.PMTimeActivity.TimeBillable AS decimal(10, 2)) / 60 *
(SELECT SalesPrice
FROM dbo.ARSalesPrice AS ARSalesPrice_1
WHERE (InventoryID = dbo.InventoryItem.InventoryID) AND (dbo.PMTimeActivity.Date >= EffectiveDate) AND (dbo.PMTimeActivity.Date <= ExpirationDate) AND (dbo.InventoryItem.CompanyID = CompanyID)) AS Amount
FROM dbo.InventoryItem
RIGHT OUTER JOIN dbo.PMTask
INNER JOIN dbo.Contract ON dbo.PMTask.CompanyID = dbo.Contract.CompanyID AND dbo.PMTask.ProjectID = dbo.Contract.ContractID
INNER JOIN dbo.PMTimeActivity ON dbo.PMTask.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.PMTask.ProjectID = dbo.PMTimeActivity.ProjectID AND dbo.PMTask.TaskID = dbo.PMTimeActivity.ProjectTaskID
ON dbo.InventoryItem.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.InventoryItem.InventoryID = dbo.PMTimeActivity.LabourItemID
WHERE (dbo.PMTimeActivity.IsCorrected = 0) AND (dbo.PMTimeActivity.IsBillable = 1) AND (dbo.PMTimeActivity.Billed = 0) AND (dbo.PMTimeActivity.DeletedDatabaseRecord <> 1)
How do I change the query such that when I add the following Group By I achieve what I want?
Group By dbo.Contract.Description, dbo.PMTask.Description
Any suggestions most welcome.
Once you correct your query such that it works (there is a missing join table) then just add an outer query which sums the amount and groups as specified e.g.
select ContractDescription, TaskDescription, sum(Amount)
from (
SELECT dbo.[Contract].[Description] ContractDescription, dbo.PMTask.[Description] TaskDescription
, CAST(dbo.PMTimeActivity.TimeBillable AS decimal(10, 2)) / 60 * (
SELECT SalesPrice
FROM dbo.ARSalesPrice AS ARSalesPrice_1
WHERE (InventoryID = dbo.InventoryItem.InventoryID) AND (dbo.PMTimeActivity.[Date] >= EffectiveDate) AND (dbo.PMTimeActivity.[Date] <= ExpirationDate) AND (dbo.InventoryItem.CompanyID = CompanyID
)) AS Amount
FROM dbo.InventoryItem
RIGHT OUTER JOIN dbo.PMTask
INNER JOIN dbo.[Contract] ON dbo.PMTask.CompanyID = dbo.[Contract].CompanyID AND dbo.PMTask.ProjectID = dbo.[Contract].ContractID
INNER JOIN dbo.PMTimeActivity ON dbo.PMTask.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.PMTask.ProjectID = dbo.PMTimeActivity.ProjectID AND dbo.PMTask.TaskID = dbo.PMTimeActivity.ProjectTaskID
/* What should go here */ ON dbo.InventoryItem.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.InventoryItem.InventoryID = dbo.PMTimeActivity.LabourItemID
WHERE (dbo.PMTimeActivity.IsCorrected = 0) AND (dbo.PMTimeActivity.IsBillable = 1) AND (dbo.PMTimeActivity.Billed = 0) AND (dbo.PMTimeActivity.DeletedDatabaseRecord <> 1)
) X
group by ContractDescription, TaskDescription;
Grouping sets with an empty set will give you a grand total for your groupings, you could use instead cube however that will also generate sub totals for each of your grouped columns as well.
SELECT dbo.Contract.Description, dbo.PMTask.Description,
CAST(dbo.PMTimeActivity.TimeBillable AS decimal(10, 2)) / 60 *
(SELECT SalesPrice
FROM dbo.ARSalesPrice AS ARSalesPrice_1
WHERE (InventoryID = dbo.InventoryItem.InventoryID) AND (dbo.PMTimeActivity.Date >= EffectiveDate) AND (dbo.PMTimeActivity.Date <= ExpirationDate) AND (dbo.InventoryItem.CompanyID = CompanyID)) AS Amount
FROM dbo.InventoryItem RIGHT OUTER JOIN
dbo.PMTask INNER JOIN
dbo.Contract ON dbo.PMTask.CompanyID = dbo.Contract.CompanyID AND dbo.PMTask.ProjectID = dbo.Contract.ContractID INNER JOIN
dbo.PMTimeActivity ON dbo.PMTask.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.PMTask.ProjectID = dbo.PMTimeActivity.ProjectID AND dbo.PMTask.TaskID = dbo.PMTimeActivity.ProjectTaskID ON
dbo.InventoryItem.CompanyID = dbo.PMTimeActivity.CompanyID AND dbo.InventoryItem.InventoryID = dbo.PMTimeActivity.LabourItemID
WHERE (dbo.PMTimeActivity.IsCorrected = 0) AND (dbo.PMTimeActivity.IsBillable = 1) AND (dbo.PMTimeActivity.Billed = 0) AND (dbo.PMTimeActivity.DeletedDatabaseRecord <> 1)
Group By Grouping Sets (dbo.Contract.Description, dbo.PMTask.Description, ())

SQL Query - How to suppress repeating values in the result set?

I'm trying to suppress the repeating values in TotalCarton column. Have tried to replace the value either blank or null but went failed. Any help?
Here is the SQL Script:
SELECT ORDERS.StorerKey,
ORDERS.OrderKey,
PackKey = (SELECT MAX(PackKey) FROM BAX_PACK_DTL WITH (NOLOCK) WHERE ORderKey = ORDERS.OrderKey),
PackHU = BAX_PACK_DTL.OuterPackID,
SalesOrderNum = ( SELECT Upper(Max(ORDERDETAIL.CustShipInst01)) FROM ORDERDETAIL WITH (NOLOCK) WHERE OrderKey = ORDERS.OrderKey),
DeliveryNum = Upper(ORDERS.ExternOrderKey),
TotalCarton = ( CASE BAX_PACK_DTL.PackType WHEN 'C' THEN Count(DISTINCT(BAX_PACK_DTL.OuterPackID))
ELSE 0 END ),
TotalPallet = ( CASE BAX_PACK_DTL.PackType WHEN 'P' THEN Count(DISTINCT(BAX_PACK_DTL.OuterPackID))
ELSE 0 END ),
SumCarton = (SELECT COUNT(DISTINCT(OuterPackSeq)) FROM BAX_PACK_DTL WITH (NOLOCK) WHERE PackType = 'C' AND PackKey = '0000000211'),
SumPallet = (SELECT COUNT(DISTINCT(OuterPackSeq)) FROM BAX_PACK_DTL WITH (NOLOCK) WHERE PackType = 'P' AND PackKey = '0000000211'),
AddWho = Upper(ORDERS.EditWho),
ORDERS.AddDate
FROM ORDERS WITH (NOLOCK) INNER JOIN ORDERDETAIL WITH (NOLOCK) ON ORDERS.StorerKey = ORDERDETAIL.StorerKey
AND ORDERS.OrderKey = ORDERDETAIL.OrderKey
INNER JOIN PICKDETAIL WITH (NOLOCK) ON ORDERDETAIL.StorerKey = PICKDETAIL.StorerKey
AND ORDERDETAIL.OrderKey = PICKDETAIL.OrderKey
AND ORDERDETAIL.OrderLineNumber = PICKDETAIL.OrderLineNumber
INNER JOIN BAX_PACK_DTL WITH (NOLOCK) ON PICKDETAIL.OrderKey = BAX_PACK_DTL.OrderKey
AND PICKDETAIL.PickDetailKey = BAX_PACK_DTL.PickDetailKey
WHERE (SELECT COUNT(DISTINCT(ORDERKEY)) FROM PICKDETAIL WITH (NOLOCK) WHERE OrderKey = ORDERS.OrderKey ) > 0
AND BAX_PACK_DTL.PackKey = '0000000211'
AND BAX_PACK_DTL.OuterPackID IN
('P111111111',
'P22222222',
'P33333333')
GROUP BY ORDERS.StorerKey,
ORDERS.OrderKey,
ORDERS.ExternOrderKey,
ORDERS.HAWB,
ORDERS.SO,
ORDERS.EditWho,
ORDERS.AddDate,
PICKDETAIL.WaveKey,
BAX_PACK_DTL.OuterPackID,
BAX_PACK_DTL.PackKey,
BAX_PACK_DTL.PackType
ORDER BY BAX_PACK_DTL.OuterPackID ASC
Below is the current result set based on the query above.
Your code looks really strange. I would expect the query to use conditional aggregation and look more like this:
SELECT ORDERS.StorerKey, ORDERS.OrderKey,
PackKey = (SELECT MAX(PackKey) FROM BAX_PACK_DTL WITH (NOLOCK) WHERE ORderKey = ORDERS.OrderKey),
PackHU = BAX_PACK_DTL.OuterPackID,
SalesOrderNum = ( SELECT Upper(Max(ORDERDETAIL.CustShipInst01)) FROM ORDERDETAIL WITH (NOLOCK) WHERE OrderKey = ORDERS.OrderKey),
DeliveryNum = Upper(ORDERS.ExternOrderKey),
TotalCarton = COUNT(DISTINCT CASE BAX_PACK_DTL.PackType WHEN 'C' THEN BAX_PACK_DTL.OuterPackID END),
TotalPallet = COUNT(DISTINCT CASE BAX_PACK_DTL.PackType WHEN 'P' THEN BAX_PACK_DTL.OuterPackID END),
SumCarton = (SELECT COUNT(DISTINCT(OuterPackSeq)) FROM BAX_PACK_DTL bpd WHERE pbd.PackType = 'C' AND pbd.PackKey = '0000000211'),
SumPallet = (SELECT COUNT(DISTINCT(OuterPackSeq)) FROM BAX_PACK_DTL bpd WHERE pbd.PackType = 'P' AND pbd.PackKey = '0000000211'),
AddWho = Upper(ORDERS.EditWho),
ORDERS.AddDate
FROM . . .
GROUP BY ORDERS.StorerKey, ORDERS.OrderKey, Upper(ORDERS.ExternOrderKey),
Upper(ORDERS.EditWho), ORDERS.AddDate;
This may not be exact. You have not qualified column names, given the table structure, and are using very arcane query syntax, mixing subqueries and aggregations. But it should give an idea.

SqlCommand: Incorrect syntax near the keyword 'OVER'

I'm trying to get data from database show it in a ASP.NET DataGrid.
It's showing the above mentioned error.
This is the select command:
public MasterJobList GetListForGrid(int RecCount, int PageNo, string OrderBy)
{
strSql = "WITH TempTable AS(Select JobDetails.JobCode,JobDetails.CurrentStatus,MasterModel.Name As ModelNumber,MasterModel.Code As ModelCode,MasterBrand.Code As BrandCode,MasterBrand.Name As BrandName,MasterDeviceType.Code As DeviceCode,MasterDeviceType.Name As DType,ROW_NUMBER() OVER (ORDER BY " + OrderBy + ") AS RowNumber From JobDetails JobDetails Inner Join MasterDeviceType ON JobDetails.DType = MasterDeviceType.Code Inner Join MasterBrand ON JobDetails.BCode = MasterBrand.Code Inner join MasterModel ON JobDetails.ModelNumber = MasterModel.Code WHERE 1 = 1) SELECT * FROM TempTable WHERE RowNumber BETWEEN {2} AND {3}";
MasterJobList objList = new MasterJobList();
DataTable dt = new DataTable();
dt = objDB.GetDataTableFromSQL(strSql);
if (dt != null)
{
foreach (DataRow Dr in dt.Rows)
{
jobs obj = new jobs();
obj.JobCode =Convert.ToInt32(Dr["JobCode"].ToString());
if (Dr["DType"] != DBNull.Value)
obj.DType = Dr["DType"].ToString();
else
obj.DType = "";
if (Dr["BrandName"] != DBNull.Value)
obj.BrandName = Dr["BrandName"].ToString();
else
obj.BrandName = "";
if (Dr["ModelNumber"] != DBNull.Value)
obj.ModelNumber = Dr["ModelNumber"].ToString();
else
obj.ModelNumber = "";
if (Dr["CurrentStatus"] != DBNull.Value)
obj.CurrentStatus = Dr["CurrentStatus"].ToString();
else
obj.CurrentStatus = "";
objList.Add(obj);
}
}
return objList;
}
The exact error is:
Exception Details: System.Data.SqlClient.SqlException: Incorrect
syntax near the keyword 'OVER'.
Please look my full code...
Your ROW_NUMBER-"column" comes after the JOINs.
Change it to:
string sql = #"
WITH TempTable AS
(
Select
JobDetails.JobCode,
JobDetails.CurrentStatus,
MasterModel.Name As ModelNumber,
MasterModel.Code As ModelCode,
MasterBrand.Code As BrandCode,
MasterBrand.Name As BrandName,
MasterDeviceType.Code As DeviceCode,
MasterDeviceType.Name As DType,
ROW_NUMBER() OVER (ORDER BY {0}) AS RowNumber
From JobDetails JobDetails
Inner Join MasterDeviceType
ON JobDetails.DType = MasterDeviceType.Code
Inner Join MasterBrand
ON JobDetails.BCode = MasterBrand.Code
Inner join MasterModel
ON JobDetails.ModelNumber = MasterModel.Code,
WHERE {1}
)
SELECT * FROM TempTable WHERE RowNumber BETWEEN {2} AND {3}";
Now use sql = String.Format(sql, orderBy, filter, rnStart, rnEnd) to assign the values.
The variables could be:
string orderBy = "ModelNumber ASC";
string filter = "BrandName = 'Sony'";
int rnStart = PageNo == 1 ? 1 : ((PageNo - 1) * RecCount) + 1;
int rnEnd = PageNo == 1 ? RecCount : PageNo * RecCount;
Update: to show the complete method (at least the relevant code) according to your edit.
public MasterJobList GetListForGrid(int RecCount, int PageNo, string OrderBy)
{
string strSql = #"
WITH TempTable AS
(
Select
JobDetails.JobCode,
JobDetails.CurrentStatus,
MasterModel.Name As ModelNumber,
MasterModel.Code As ModelCode,
MasterBrand.Code As BrandCode,
MasterBrand.Name As BrandName,
MasterDeviceType.Code As DeviceCode,
MasterDeviceType.Name As DType,
ROW_NUMBER() OVER (ORDER BY {0}) AS RowNumber
From JobDetails JobDetails
Inner Join MasterDeviceType
ON JobDetails.DType = MasterDeviceType.Code
Inner Join MasterBrand
ON JobDetails.BCode = MasterBrand.Code
Inner join MasterModel
ON JobDetails.ModelNumber = MasterModel.Code,
WHERE {1}
)
SELECT * FROM TempTable WHERE RowNumber BETWEEN {2} AND {3}";
int rnStart = PageNo == 1 ? 1 : ((PageNo - 1) * RecCount) + 1;
int rnEnd = PageNo == 1 ? RecCount : PageNo * RecCount;
strSql = String.Format(strSql, OrderBy, "1=1", rnStart, rnEnd);
DataTable dt = objDB.GetDataTableFromSQL(strSql);
// ...
return objList;
}
please check this example in ssms and change the accordingly.
declare #t table(name varchar(50))
insert into #t values ('a'),('b'),('c'),('d'),('e')
select ROW_NUMBER() over ( order by name)
, name
from #t
Check the comment, you just apply the "orderby" by value
WITH temptable
AS (SELECT jobdetails.jobcode,
jobdetails.currentstatus,
mastermodel.NAME AS ModelNumber,
mastermodel.code AS ModelCode,
masterbrand.code AS BrandCode,
masterbrand.NAME AS BrandName,
masterdevicetype.code AS DeviceCode,
masterdevicetype.NAME AS DType,
Row_number()
OVER (
ORDER BY " + orderby + ") AS RowNumber --here you have to assign the order by value
FROM jobdetails JobDetails
INNER JOIN masterdevicetype
ON jobdetails.dtype = masterdevicetype.code
INNER JOIN masterbrand
ON jobdetails.bcode = masterbrand.code
INNER JOIN mastermodel
ON jobdetails.modelnumber = mastermodel.code
WHERE 1 = 1)
SELECT *
FROM temptable
WHERE rownumber BETWEEN {2} AND {3}

Adding a SUM Column to a Query

I'm trying to do a query that returns the information of a purchase bill, but also there's another table that has detail of the bill, but I need to add that total to the other query, but I can't add the column, because it says that I need to have in the group by the same objects that in the select, and I tried it this way, but it says that it returns more than one value. Help please! :D
SELECT fc.fecha_factura_compra AS fecha, fc.id_factura AS no_factura, fc.serie,
o.abreviatura + CAST(p.corr_id AS VARCHAR(255)) AS codigo_trupp,
p.nombre, fc.dias_credito, fc.tipo_cambio,
(SELECT SUM(dc.peso_neto * dc.precio_unitario)
FROM detalle_compra AS dc
GROUP BY dc.id_proveedor,
dc.id_factura,
dc.serie) AS total
FROM factura_compra AS fc,
origen AS o,
proveedor AS p,
detalle_compra AS dc
WHERE fc.id_proveedor = p.id_proveedor
AND dc.id_proveedor = p.id_proveedor
AND dc.id_factura = fc.id_factura
AND p.id_origen = o.id_origen
AND dc.serie = fc.serie
AND dc.id_factura = fc.id_factura
AND dc.id_proveedor = fc.id_proveedor
AND fc.activo_inactivo = 'true'
AND fc.anulada = 'false'
The construction with the subquery is extremely slow and to be avoided. A better solution is to write the query like below.
To add a total to a query you need to group by over all the other fields in your result set.
SELECT fc.fecha_factura_compra AS fecha
, fc.id_factura AS no_factura
, fc.serie
, o.abreviatura + CAST(p.corr_id AS VARCHAR(255)) AS codigo_trupp
, p.nombre
, fc.dias_credito
, fc.tipo_cambio
, SUM(dc.peso_neto * dc.precio_unitario) AS total
FROM factura_compra AS fc
JOIN proveedor AS p
ON fc.id_proveedor = p.id_proveedor
JOIN origen AS o
ON p.id_origen = o.id_origen
JOIN detalle_compra AS dc
ON dc.id_factura = fc.id_factura
AND dc.serie = fc.serie
AND dc.id_factura = fc.id_factura
AND dc.id_proveedor = fc.id_proveedor
AND dc.id_proveedor = p.id_proveedor
WHERE fc.activo_inactivo = 'true'
AND fc.anulada = 'false'
GROUP BY fc.fecha_factura_compra
, fc.id_factura
, fc.serie
, o.abreviatura + CAST(p.corr_id AS VARCHAR(255))
, p.nombre
, fc.dias_credito
, fc.tipo_cambio
Instead of grouping by the columns, you should restrict the sub-select on the join columns and omit detalle_compra from the outer select:
SELECT fc.fecha_factura_compra as fecha,
fc.id_factura as no_factura,
fc.serie,
o.abreviatura+CAST(p.corr_id as varchar(255)) as Codigo_Trupp,
p.nombre,
fc.dias_credito,
fc.tipo_cambio,
(select sum(peso_neto*precio_unitario)
from detalle_compra
where serie = fc.serie and
id_factura = fc.id_factura and
id_proveedor = fc.id_proveedor) as Total
FROM factura_compra as fc,origen as o, proveedor as p
WHERE fc.id_proveedor = p.id_proveedor and
p.id_origen = o.id_origen and
fc.activo_inactivo = 'true' and
fc.anulada = 'false'
Side note: Use the BIT type to store booleans:
...
fc.activo_inactivo = 1 and
fc.anulada = 0