SQL Syntax Error Group By - sql

I've got a sql syntax and it gives me the error:
Msg 8120, Level 16, State 1, Line 1 Column 'VEHICLEMASTR.cconduction'
is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
Here is the SQL syntax:
SELECT A.cplateno,A.cconduction,A.cname,A.cbatterymodel
,A.dbattery,A.DlastChange,A.nlastoilkm,A.naveragekmday
,A.dkmreading,A.dfranacq,A.dfranexp,A.nlimit,A.dreading
,CONVERT(varchar(2),month(MAX(B.dinsexp)))+'/'+CONVERT(varchar(2),day(MAX(B.dinsexp)))+'/'+CONVERT(varchar(4),year(MAX(B.dinsexp))) as dinsexp
,C.corno,CONVERT(varchar(2),month(MAX(C.dregexp)))+'/'+CONVERT(varchar(2),day(MAX(C.dregexp)))+'/'+ CONVERT(varchar(4),year(MAX(C.dregexp))) as dregexp
FROM VEHICLEMASTR A
LEFT JOIN VEHICLEINSURANCE B
ON A.cplateno = B.cplateno
LEFT JOIN VREGISTRATION C
ON A.cplateno = C.cplateno
GROUP BY A.cplateno
Can anybody tell what went wrong?

The "group by" clause must name every column selected, except those columns that are aggregate functions.
FYI an "aggregate" function is one that returns a single value for many rows, like sum(), count(), etc

a.cconduction needs to be in the group by clause.
When using a Group By clause, a column must either have an aggregate function (i.e. COUNT) or be defined in the group by.
A sample group by statement with multiple grouping:
SELECT column1_name, column2_name, aggregate_function(column_name3)
FROM table_name
WHERE column_name1 operator value
GROUP BY column_name1, column_name2;

You must include all fields that you mentioned in your select except the column that has aggregate function so in your case it would be:
GROUP BY
a.cplateno, a.cconduction,a.cname,a.cbatterymodel,a.dbattery,
a.DlastChange,a.nlastoilkm,a.naveragekmday,
a.dkmreading,a.dfranacq,a.dfranexp,a.nlimit,a.dreading
instead of
GROUP BY a.cplateno
Edit:
If you want only the a.cplateno then you don't include the rest of the fields except aggregate function and a.cplateno like:
SELECT A.cplateno
,CONVERT(varchar(2),month(MAX(B.dinsexp)))+'/'+CONVERT(varchar(2),day(MAX(B.dinsexp)))+'/'+CONVERT(varchar(4),year(MAX(B.dinsexp))) as dinsexp
,CONVERT(varchar(2),month(MAX(C.dregexp)))+'/'+CONVERT(varchar(2),day(MAX(C.dregexp)))+'/'+ CONVERT(varchar(4),year(MAX(C.dregexp))) as dregexp
FROM VEHICLEMASTR A
LEFT JOIN VEHICLEINSURANCE B
ON A.cplateno = B.cplateno
LEFT JOIN VREGISTRATION C
ON A.cplateno = C.cplateno
GROUP BY A.cplateno

Related

Issue using HAVING-Clause: Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) [duplicate]

I am using Firebird SQL. The below mentioned query returns 4 rows as shown in the figure.
SELECT a.EPS_ID,b.C_NAME,c.AY_YR_NAME,d.S_NAME,e.E_NAME
FROM
TBLEXAMPLANNER_S_MSB a,
TBLCLASS_MSB b,
TBLACADEMICYEAR_MSB c,
TBLSUBJECTS_MSB d,
TBLEXAMTYPE_MSB e
WHERE
a.EPS_CLASS_ID=b.C_ID
AND a.EPS_SESSION_ID=c.AY_ID
AND a.EPS_SUB_ID=d.S_ID
AND a.EPS_PE_ID=e.E_ID
I want it to return only 1(one) row like
EPS_ID C_NAME AY_YR_NAME S_NAME E_NAME
---------------------------------------------------
7 5 2016-2017 English FA1
I am using the following query but it does not work.
SELECT a.EPS_ID,MAX(b.C_NAME) AS XT,c.AY_YR_NAME,d.S_NAME,e.E_NAME
FROM
TBLEXAMPLANNER_S_MSB a,
TBLCLASS_MSB b,
TBLACADEMICYEAR_MSB c,
TBLSUBJECTS_MSB d,
TBLEXAMTYPE_MSB e
WHERE
a.EPS_CLASS_ID=b.C_ID
AND a.EPS_SESSION_ID=c.AY_ID
AND a.EPS_SUB_ID=d.S_ID
AND a.EPS_PE_ID=e.E_ID
GROUP BY a.EPS_ID,d.S_NAME
The error message is :
Invalid expression in the select list (not contained in either an
aggregate function or the GROUP BY clause)
The usage of GROUP BY makes the engine group the records for you. To do grouping, you have to give advice to the RDBMS for each column, what it should do.
Group it? -> Add column to GROUP BY-Clause
Not group it? -> ok, what else?
ignore the column? remove it from your select-clause
Sum it? -> use SUM(mycol)
other aggregation functions can be found in the documentation
Additionally: In your case you try to group by EPS_ID, which is unique in each row. So a grouping by that column will return all rows, because there is nothing to group by. To group records, they have to have the same value.
Learn to use proper, explicit JOIN syntax.
Your problem is that all unaggregated columns need to be in the GROUP BY:
SELECT a.EPS_ID, MAX(b.C_NAME) AS XT, c.AY_YR_NAME, d.S_NAME, e.E_NAME
FROM TBLEXAMPLANNER_S_MSB a JOIN
TBLCLASS_MSB b
ON a.EPS_CLASS_ID = b.C_ID JOIN
TBLACADEMICYEAR_MSB c
ON a.EPS_SESSION_ID = c.AY_ID JOIN
TBLSUBJECTS_MSB d
ON a.EPS_SUB_ID = d.S_ID JOIN
TBLEXAMTYPE_MSB e
ON a.EPS_PE_ID = e.E_ID
GROUP BY a.EPS_ID, c.AY_YR_NAME, d.S_NAME, e.E_NAME;
Note: I would also recommend that you use table abbreviations for table aliases. So, ep for TBLEXAMPLANNER_S_MSB instead of a. Arbitrary table aliases make the query hard to follow.
Try
SELECT a.EPS_ID,c.AY_YR_NAME,d.S_NAME,e.E_NAME,MAX(b.C_NAME) AS XT ...
GROUP BY 1,2,3,4

Using trunc and concatenate command with Join

select EDR_Process_Time, MSISDN1, Total_payment/Total_data_MB from
(
select trunc(M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time) as EDR_Process_Time, M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN as MSISDN1, trunc(M_MOBILEMV.Q_RA_CDR_DETAILS_V.CDR_start_Date), M_MOBILEMV.Q_RA_CDR_DETAILS_V.served_msisdn, sum(M_MOBILEMV.Q_RA_CDR_DETAILS_V.charge_fee_1) as Charge_fee_CDR,
sum(M_MOBILEMV.Q_RA_EDR_DETAILS_V.charge_fee/100) as Total_Payment,
sum(M_MOBILEMV.Q_RA_EDR_DETAILS_V.amount/1048576) as Total_data_MB,
from (M_MOBILEMV.Q_RA_EDR_DETAILS_V
left join M_MOBILEMV.Q_RA_CDR_DETAILS_V on concat(trunc(M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time), M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN) = concat(trunc(M_MOBILEMV.Q_RA_CDR_DETAILS_V.CDR_start_date), M_MOBILEMV.Q_RA_CDR_DETAILS_V.served_MSISDN))
group by trunc(M_MOBILEMV.Q_RA_EDR_DETAILS_V.Process_time), M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN
group by trunc(M_MOBILEMV.Q_RA_CDR_DETAILS_V.CDR_start_Date), M_MOBILEMV.Q_RA_CDR_DETAILS_V.Served_MSISDN
)
Syntax of functions is wrong. Use trunc function as trunc(M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time). Usege of sum is wrong too. You also should change them to sum(M_MOBILEMV.Q_RA_CDR_DETAILS_V.charge_fee_1.
First, wrong syntax at M_MOBILEMV.Q_RA_EDR_DETAILS_V.sum((charge_fee)/100) and other similar expressions.
If you want sum of charge_fee/100 column of the M_MOBILEMV.Q_RA_EDR_DETAILS_V table (view) it must
be
sum(M_MOBILEMV.Q_RA_EDR_DETAILS_V.charge_fee/100)
Next, you can not use an alias in the same SELECT list where it was introduced. Total_Payment and Total_data_MB should only apprear in expressions at outer SELECT.
Assign aliases to the every expression of the inner select, an alias to the inner select itself and use list of qualified names and expresions using those names instead of * in the outer select.
Also, it looks like GROUP BY is missing.
select t.process_time, t.MSISDN, t.sum1,
t.Total_Payment,
t.Total_data_MB,
t.Total_Payment/t.Total_data_MB as cost_per_MB
from (
select
M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time,
M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN,
sum(M_MOBILEMV.Q_RA_CDR_DETAILS_V.charge_fee_1) as sum1,
(coalesce(sum(M_MOBILEMV.Q_RA_CDR_DETAILS_V.charge_fee_1),0) + coalesce(sum(M_MOBILEMV.Q_RA_EDR_DETAILS_V.charge_fee/100),0)) as Total_Payment,
sum(M_MOBILEMV.Q_RA_EDR_DETAILS_V.amount)/1048576 as Total_data_MB
-- Don't you mean
--GROUP BY M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time, M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN
from (M_MOBILEMV.Q_RA_EDR_DETAILS_V
left join M_MOBILEMV.Q_RA_CDR_DETAILS_V on concat(trunc(M_MOBILEMV.Q_RA_EDR_DETAILS_V.process_time), M_MOBILEMV.Q_RA_EDR_DETAILS_V.MSISDN) = concat(trunc(M_MOBILEMV.Q_RA_CDR_DETAILS_V.CDR_start_date), M_MOBILEMV.Q_RA_CDR_DETAILS_V.served_MSISDN)
) t
)

how is the expression invalid in my simple query?

I'm new to SQL, creating a simple query from an identical example but not sure why 1 expression is invalid?
I tried this statement:
SELECT
A.AccountId,
A.Address1_City,
A.Address1_Country,
A.Address1_PostalCode,
A.Address1_StateOrProvince,
A.CreatedOn,
A.EMailAddress1,
A.mcs_ABN2,
A.mcs_AdminContact,
A.mcs_AdminContactName,
A.mcs_AreyouinterestedinInternationalDevelopmen,
A.mcs_BenefitsUtilised,
A.mcs_BusinessNameOrganisationName,
A.mcs_doyouprovideaccreditedtraining,
A.mcs_doyouprovidenonaccreditedtraining,
A.mcs_DoyouprovideservicesinanyNDISTrialSites,
A.mcs_DoyouprovideservicestoChildrenYoungPeople,
A.mcs_DummyRecord,
A.mcs_EntityStatusCode,
A.mcs_IndustryOperatingIn,
A.mcs_IsStreetAddresssameasPostalAddress,
A.mcs_MembershipNote,
A.mcs_MultiStateDepartment,
A.mcs_NotefromApplicant,
A.mcs_NumberofEmployeesDec,
A.mcs_OtherTradingNameOrganisationName,
A.mcs_PartnerDisabilityServiceOrganisations,
A.mcs_PrimaryProductsServicesToPromote,
A.mcs_RevenueDisabServiceProvisionTotalAnnual,
A.mcs_SageERPCustomerCode,
A.mcs_SageErpExportFlag,
A.ModifiedOn,
A.Name,
A.nds_Account_MembershipNumberCopy,
A.nds_IsMember,
A.nds_MainContact,
A.nds_MainContactName,
A.nds_MemberCategoryCopy,
A.PrimaryContactId,
A.Revenue,
A.Revenue_Base,
A.StatusCode,
A.WebSiteURL
FROM
account A
WHERE
A.statuscode = 1
GROUP BY
A.name
and got this error:
ERROR [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'account.AccountId' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Group By is for aggregate functions (Count, Sum, etc), so if you use group by you need to group by at least every column being returned in the select SQL, otherwise it wouldn't be able to do the aggregation. This looks like you just want to order by Name though, so if you replace
GROUP BY A.name
with
ORDER BY A.name
it should work. If you don't care about order or aggregation just remove that part of the query entirely.

Filter on column values not in select

I am trying to do joins on two tables and filter on values that are not in my select statement.
The following query does not work.
select b.[[Product]].[Major Category]]] ,sum(a.BIC_ZCDP) from TEMP_FORECAST_ALL a
join OUT_Dimension_DP_Product b
on right(a.MATERIAL,10) = b.[[Product]].[10D]]]
join OUT_Dimension_DP_Market c
on a.BIC_ZRMARKET = c.[[Market]].[Market]]]
group by b.[[Product]].[Major Category]]]
having a.CALMONTH in ('201810','201811','201812') and c.[[Market]].[Region]]] = 'UK'
I get the following errors
Msg 8121, Level 16, State 1, Line 7
Column 'TEMP_FORECAST_ALL.CALMONTH' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8121, Level 16, State 1, Line 7
Column 'TEMP_FORECAST_ALL.CALMONTH' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8121, Level 16, State 1, Line 7
Column 'TEMP_FORECAST_ALL.CALMONTH' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8121, Level 16, State 1, Line 7
Column 'OUT_Dimension_DP_Market.[Market].[Region]' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
I don't want to add Region and CALMONTH in my group by clause.
Use a WHERE clause . . . :
select p.[[Product]].[Major Category]]], sum(a.BIC_ZCDP)
from TEMP_FORECAST_ALL a join
OUT_Dimension_DP_Product p
on right(a.MATERIAL,10) = b.[[Product]].[10D]]] join
OUT_Dimension_DP_Market m
on a.BIC_ZRMARKET = m.[[Market]].[Market]]]
where a.CALMONTH in ('201810', '201811', '201812') and
m.[[Market]].[Region]]] = 'UK'
group by p.[[Product]].[Major Category]]];
having is only for aggregates. Since this is just simple comparisons, you want them in a where clause. You'd use having if you were, for example, comparing to a sum or other aggregate.
Having clause is used when we are using aggregate function, but here you are simply doing comparison so you have to go with where clause.
A HAVING clause is used when you are filtering on aggregated data, i.e., if you wanted to filter on the results of the SUM statement, something like the following:
HAVING SUM(a.BIC_ZCDP) > 0
However, for the purposes of your query, you simply need to switch the HAVING to WHERE, as so...
SELECT
b.[[Product]].[Major Category]]],
SUM(a.BIC_ZCDP)
FROM
TEMP_FORECAST_ALL a
INNER JOIN OUT_Dimension_DP_Product b ON right(a.MATERIAL,10) = b.[[Product]].[10D]]]
INNER JOIN OUT_Dimension_DP_Market c ON a.BIC_ZRMARKET = c.[[Market]].[Market]]]
WHERE
(a.CALMONTH IN ('201810','201811','201812')) AND (c.[[Market]].[Region]]] = 'UK')
GROUP BY
b.[[Product]].[Major Category]]]
Again, a HAVING clause allows you to filter on fields that have been AGGREGATED (SUM, MAX, MIN, etc.), while a WHERE clause allows you to filter on normal fields.

ORACLE GROUP BY error

My SQL query is the following:
SELECT
oh.ORDER_NUMBER, oh.CREATED_TS, stat.STATE, stat.TIMESTAMP
FROM
IMPL_OH_ORDER_HEADER oh,
SNCR_ORDER_DISPOSITION stat,
SNCR_ORDER_DISP_HEAD stathead,
IMPL_CUST_ACCOUNT cust
WHERE
stat.DISP_TRANSACTION_ID=stathead.DISP_TRANSACTION_ID
and stathead.TRANSACTION_ID=oh.TRANSACTION_ID
and oh.ACCOUNT_ID=cust.ACCOUNT_ID
and stat.CATEGORY=100
and oh.USER_ID='a'
and cust.ACCOUNT_NUM='123'
GROUP BY oh.ORDER_NUMBER
ORDER BY stat.TRX_SEQ DESC;
It is giving the following error: ORA-00979: not a GROUP BY expression
If I remove the GROUP BY expression, I don't get the error.
What is correct GROUP BY syntax?
Research: A google search says that, if AGGREGATE functions are used, I should have all fields not used by aggregate function in the GROUP BY clause. So I tried to modify the GROUP BY expression to GROUP BY oh.ORDER_NUMBER, oh.CREATED_TS, stat.TIMESTAMP, stat.STATE.
Yet I am getting the same error.
Please help.
You get the error because you have STAT.TRX_SEQ in the order by list.
If you use the group by clause together with the order by clause, you must either order by a column on which you grouped or on an aggregated value.
This rule also applies to the selected values: they're either part of the group by or aggregate functions (or pseudo columns).
Can you try this one and see??
SELECT OH.ORDER_NUMBER,
OH.CREATED_TS,
STAT.STATE,
STAT.TIMESTAMP
FROM IMPL_OH_ORDER_HEADER OH,
SNCR_ORDER_DISPOSITION STAT,
SNCR_ORDER_DISP_HEAD STATHEAD,
IMPL_CUST_ACCOUNT CUST
WHERE STAT.DISP_TRANSACTION_ID = STATHEAD.DISP_TRANSACTION_ID
AND STATHEAD.TRANSACTION_ID = OH.TRANSACTION_ID
AND OH.ACCOUNT_ID = CUST.ACCOUNT_ID
AND STAT.CATEGORY = 100
AND OH.USER_ID = 'A'
AND CUST.ACCOUNT_NUM = '123'
GROUP BY OH.ORDER_NUMBER,
OH.CREATED_TS,
STAT.STATE,
STAT.TIMESTAMP
ORDER BY STAT.TRX_SEQ DESC;