SELECT DISTINCT, ORDER BY expressions must appear in target list - sql

I have done this SQL request :
SELECT DISTINCT
*, j_start_date, typeNP.j_value, g_challenge.j_title
FROM g_challenge
INNER JOIN g_challenge_catset typeNP ON g_challenge.j_row_id = typeNP.j_item_id AND typeNP.j_value IN ('jbm_5233','jbm_5232','bfr_8227')
INNER JOIN g_challenge_catset as tps ON g_challenge.j_row_id = tps.j_item_id AND tps.j_value IN ('aga_7777','aga_7778','aga_7776')
LEFT OUTER JOIN g_dbsocialgroup gdb ON g_challenge.j_dbsocialgroup_id = gdb.j_row_id || '_DBSocialGroup'
WHERE (j_start_date >= '2018-08-13' OR (j_start_date <= '2018-08-13' AND j_end_date >= '2018-08-13')) AND g_challenge.j_pstatus = 0 AND g_challenge.j_mutualiste_type = false
ORDER BY
CASE typeNP.j_value
WHEN 'bfr_8227' THEN '1'
WHEN 'jbm_5233' THEN '2'
WHEN 'jbm_5232' THEN '3'
END,
j_start_date ASC, g_challenge.j_title ASC
But I got this error : SELECT DISTINCT, ORDER BY expressions must appear in target list and I don't know why ?
Help me please

Ok, I solved this with a group by
GROUP BY g_challenge.j_start_date, typeNP.j_value, g_challenge.j_title, g_challenge.j_row_id, typeNP.j_item_id, tps.j_item_id, tps.j_value, gdb.j_row_id
and with removing the DISTINCT and named columns in the select

Related

How to solve this error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery?

I have a query that works on SQLAnywhere, but for some reason does not work on SSMS, tell me what is wrong with it, because I get an error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
SELECT (CASE
WHEN EXISTS (select 1 from READCHK_READSEQ_OVRCOMP where READCHK_ID = :readChkId AND READSEQ_ID = :readSeqId) THEN 'M'
WHEN ( COUNT(*) = Coalesce(SUM((SELECT COUNT(*) FROM READCHKFLEX flx WHERE flx.READCHKFLD_ID = rcfld.READCHKFLD_ID AND flx.READCHK_ID = :readChkId) ), 0 )) THEN 'A'
ELSE 'I' END) CompletionStatus
FROM READSEQFLD rsfld
JOIN READSEQ rseq on rseq.READSEQ_ID = rsfld.READSEQ_ID
JOIN READCHKPAGEFLD rcpf on rcpf.READCHKTYPE_ID = rseq.READCHKTYPE_ID and rcpf.READCHKFLD_ID = rsfld.READCHKFLD_ID
JOIN READCHKFLD rcfld on rcfld.READCHKFLD_ID = rcpf.READCHKFLD_ID
WHERE rsfld.READSEQ_ID = :readSeqId
AND Upper(rsfld.ACTIVATE_FLG) = 'Y'
AND rcfld.CALFORM_ID IS NULL
AND (rcpf.fld_properties is null or Upper(rcpf.fld_properties) <> 'HIDE');
How to fix that?
SQL Server doesn't allow aggregates on expressions containing sub queries.
I think the following should preserve your original behaviour
Append a CTE definition before the existing SELECT
WITH flx_agg
AS (SELECT COUNT(*) AS Cnt,
READCHKFLD_ID
FROM READCHKFLEX flx
WHERE flx.READCHK_ID = :readChkId
GROUP BY READCHKFLD_ID)
SELECT ...
Add an outer join to that to your existing join conditions
LEFT JOIN flx_agg
ON flx_agg.READCHKFLD_ID = rcfld.READCHKFLD_ID
Change the offending CASE WHEN condition to
WHEN COUNT(*) = COALESCE(SUM(flx_agg.Cnt), 0)

SQL-Query (with subquery, group and order by) optimization

coud you help me optimizing the following statement. It has a bad prerformance when dealing with huge amount of data (in my case 3Mio Messages and 25Mio MessageWorkItems).
Does anybody have any suggestions? Thank you in advance.
select distinct msg.id, msgWorkItem_1.description
from message msg
left outer join message_work_item msgWorkItem_1 on msg.id=msgWorkItem_1.message_id
and ( msgWorkItem_1.id in (
select max(msgWorkItem_2.id)
from message_work_item msgWorkItem_2
inner join message_work_item_type msgWorkItem_Type on msgWorkItem_2.message_work_item_type_id=msgWorkItem_Type.id
where
msgWorkItem_2.creation_type= 'mobile'
and msgWorkItem_2.description is not null
and msgWorkItem_Type.code <> 'sent-to-app-manually'
-- Is it possible to avoid this correlation to the outer query ? )
and msgWorkItem_2.message_id = msg.id)
)
where msg.deactivation_time > ?
order by msgWorkItem_1.description asc
STEP 1 : Lay out the query so I have any hope of reading it
SELECT
DISTINCT
msg.id,
msgWorkItem_1.description
FROM
message msg
LEFT OUTER JOIN
message_work_item AS msgWorkItem_1
ON msgWorkItem_1.message_id = msg.id
AND msgWorkItem_1.id =
(
SELECT
MAX(msgWorkItem_2.id)
FROM
message_work_item AS msgWorkItem_2
INNER JOIN
message_work_item_type AS msgWorkItem_Type
ON msgWorkItem_2.message_work_item_type_id=msgWorkItem_Type.id
WHERE
msgWorkItem_2.creation_type= 'mobile'
AND msgWorkItem_2.description IS NOT NULL
AND msgWorkItem_Type.code <> 'sent-to-app-manually'
-- Is it possible to avoid this correlation to the outer query ?
AND msgWorkItem_2.message_id = msg.id
)
WHERE
msg.deactivation_time > ?
ORDER BY
msgWorkItem_1.description ASC
STEP 2 : rewrite using analytic functions instead of MAX()
SELECT
DISTINCT
message.id,
message_work_item_sorted.description
FROM
message
LEFT OUTER JOIN
(
SELECT
message_work_item.message_id,
message_work_item.description,
ROW_NUMBER() OVER (PARTITION BY message_work_item.message_id
ORDER BY message_work_item.id DESC
)
AS row_ordinal
FROM
message_work_item
INNER JOIN
message_work_item_type
ON message_work_item.message_work_item_type_id = message_work_item_type.id
WHERE
message_work_item.creation_type= 'mobile'
AND message_work_item.description IS NOT NULL
AND message_work_item_type.code <> 'sent-to-app-manually'
)
message_work_item_sorted
ON message_work_item_sorted.message_id = message.id
AND message_work_item_sorted.row_ordinal = 1
WHERE
message.deactivation_time > ?
ORDER BY
message_work_item_sorted.description ASC
With more information we could probably help further, but as you gave no definition of the tables, constraints, or business logic, this is just a re-write of what you're already implemented.
For example, I strongly doubt you need the DISTINCT (provided that the id columns in your tables are unique).

subquery from SELECT reference, gets me a "cannot be referenced from this part of the query"

I'm dealing with this question
I know the simple aggregate answer, but I figured out to try to challenge myself with subqueries.
SELECT outercm.surname, outercm.firstname, outercm.memid, subq.starttime
FROM cd.members outercm,
(
SELECT cm.memid, cb.starttime
from cd.members cm
JOIN cd.bookings cb ON cb.memid = cm.memid
WHERE cm.memid = outercm.memid
AND
DATE(starttime ) >= '01-09-2012'
ORDER BY cb.starttime
LIMIT 1
) as subq
And I get this error:
There is an entry for table "outercm", but it cannot be referenced
from this part of the query.
I've also tried subqueries from the FROM:
SELECT outercm.surname, outercm.firstname, outercm.memid,
(
SELECT cb.starttime
from cd.members cm
JOIN cd.bookings cb ON cb.memid = cm.memid
WHERE cm.memid = outercm.memid
AND
DATE(starttime ) >= '01-09-2012'
ORDER BY cb.starttime
LIMIT 1
)
FROM cd.members outercm
And i get this message:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
I'm not sure, when and how can i reference betweein inner and outer queries.
Thanks for the help
In Postgres, DISTINCT ON can be used to get results for highest/lowest row per group, in your example the "first booking". This is generally far efficient when compared to other options like GROUP BY + MIN() or using LIMIT in a correlated sub-query.
SELECT DISTINCT ON ( cm.memid ) cm.surname,
--get the first among memid
cm.firstname,
cm.memid,
cb.starttime
FROM cd.members cm
join cd.bookings cb
ON cb.memid = cm.memid
AND cb.starttime >= TIMESTAMP '2012-09-01'
ORDER BY cm.memid, --for each memid
cb.starttime; --that has the earliest date

Should a subquery on a join use tables from an outer query in the where clause?

I need to add a subquery to a join, because one payment can have more than one allotment, so I only need to account for the first match (where rownum = 1).
However, I'm not sure if adding pmt from the outer query to the subquery on the allotment join is best.
Should I be doing this differently in the event of performance hits, etc.. ?
SELECT
pmt.payment_uid,
alt.allotment_uid,
FROM
payment pmt
/* HERE: is the reference to pmt.pay_key and pmt.client_id
incorrect in the below subquery? */
INNER JOIN allotment alc ON alt.allotment_uid = (
SELECT
allotment_uid
FROM
allotment
WHERE
pay_key = pmt.pay_key
AND
pay_code = 'xyz'
AND
deleted = 'N'
AND
client_id = pmt.client_id
AND
ROWNUM = 1
)
WHERE
AND
pmt.deleted = 'N'
AND
pmt.date_paid >= TO_DATE('2017-07-01')
AND
pmt.date_paid < TO_DATE('2017-10-01') + 1;
It's difficult to identify the performance issue in your query without seeing an explain plan output. You query does seem to do an additional SELECT on the allotment for every record from the main query.
Here is a version which doesn't use correlated sub query. Obviously I haven't been able to test it. It does a simple join in and then filters all records except one of the allotments. Hope this helps.
WITH v_payment
AS
(
SELECT
pmt.payment_uid,
alt.allotment_uid,
ROW_NUMBER () OVER(PARTITION BY allotment_id) r_num
FROM
payment pmt JOIN allotment alt
ON (pmt.pay_key = alt.pay_key AND
pmt.client_id = alt.client_id)
WHERE pmt.deleted = 'N' AND
pmt.date_paid >= TO_DATE('2017-07-01') AND
pmt.date_paid < TO_DATE('2017-10-01') + 1 AND
alt.pay_code = 'xyz' AND
alt.deleted = 'N'
)
SELECT payment_uid,
allotment_uid
FROM v_payment
WHERE r_num = 1;
Let's know how this performs!
You can phrase the query that way. I would be more likely to do:
SELECT . . .
FROM payment p INNER JOIN
(SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY pay_key, client_id
ORDER BY allotment_uid
) as seqnum
FROM allotment a
WHERE pay_code = 'xyz' AND deleted = 'N'
) a
ON a.pay_key = p.pay_key AND a.client_id = p.client_id AND
seqnum = 1
WHERE p.deleted = 'N' AND
p.date_paid >= DATE '2017-07-01' AND
p.date_paid < (DATE '2017-10-01') + 1;

Column is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause

Ok here's my View (vw_LiftEquip)
SELECT dbo.tbl_equip_swl_unit.unit_id,
dbo.tbl_equip_swl_unit.unit_name,
dbo.tbl_equip_swl_unit.archived,
dbo.tbl_categories.category_id,
dbo.tbl_categories.categoryName,
dbo.tbl_categories.parentCategory,
dbo.tbl_categories.sub_category,
dbo.tbl_categories.desc_category,
dbo.tbl_categories.description,
dbo.tbl_categories.miscellaneous,
dbo.tbl_categories.category_archived,
dbo.tbl_equip_swl_unit.unit_name AS Expr1,
dbo.tbl_categories.categoryName AS Expr2,
dbo.tbl_categories.description AS Expr3,
dbo.tbl_equip_depts.dept_name,
dbo.tbl_equip_man.man_name,
dbo.tbl_Lifting_Gear.e_defects AS Expr7,
dbo.tbl_Lifting_Gear.e_defects_desc AS Expr8,
dbo.tbl_Lifting_Gear.e_defects_date AS Expr9,
dbo.tbl_equipment.equipment_id,
dbo.tbl_equipment.e_contract_no,
dbo.tbl_equipment.slID,
dbo.tbl_equipment.e_entered_by,
dbo.tbl_equipment.e_serial,
dbo.tbl_equipment.e_model,
dbo.tbl_equipment.e_description,
dbo.tbl_equipment.e_location_id,
dbo.tbl_equipment.e_owner_id,
dbo.tbl_equipment.e_department_id,
dbo.tbl_equipment.e_manafacture_id,
dbo.tbl_equipment.e_manDate1,
dbo.tbl_equipment.e_manDate2,
dbo.tbl_equipment.e_manDate3,
dbo.tbl_equipment.e_dimensions,
dbo.tbl_equipment.e_test_no,
dbo.tbl_equipment.e_firstDate1,
dbo.tbl_equipment.e_firstDate2,
dbo.tbl_equipment.e_firstDate3,
dbo.tbl_equipment.e_prevDate1,
dbo.tbl_equipment.e_prevDate2,
dbo.tbl_equipment.e_prevDate3,
dbo.tbl_equipment.e_insp_frequency,
dbo.tbl_equipment.e_swl,
dbo.tbl_equipment.e_swl_unit_id,
dbo.tbl_equipment.e_swl_notes,
dbo.tbl_equipment.e_cat_id,
dbo.tbl_equipment.e_sub_id,
dbo.tbl_equipment.e_parent_id,
dbo.tbl_equipment.e_last_inspector,
dbo.tbl_equipment.e_last_company,
dbo.tbl_equipment.e_deleted AS Expr11,
dbo.tbl_equipment.e_deleted_desc AS Expr12,
dbo.tbl_equipment.e_deleted_date AS Expr13,
dbo.tbl_equipment.e_deleted_insp AS Expr14,
dbo.tbl_Lifting_Gear.e_defects_action AS Expr15,
dbo.tbl_equipment.e_rig_location,
dbo.tbl_Lifting_Gear.e_add_type AS Expr17,
dbo.tbl_Lifting_Gear.con_id,
dbo.tbl_Lifting_Gear.lifting_date,
dbo.tbl_Lifting_Gear.lifting_ref_no,
dbo.tbl_Lifting_Gear.e_id,
dbo.tbl_Lifting_Gear.inspector_id,
dbo.tbl_Lifting_Gear.lift_testCert,
dbo.tbl_Lifting_Gear.lift_rig_location,
dbo.tbl_Lifting_Gear.inspected,
dbo.tbl_Lifting_Gear.lifting_through,
dbo.tbl_Lifting_Gear.liftingNDT,
dbo.tbl_Lifting_Gear.liftingTest,
dbo.tbl_Lifting_Gear.e_defects,
dbo.tbl_Lifting_Gear.e_defects_desc,
dbo.tbl_Lifting_Gear.e_defects_date,
dbo.tbl_Lifting_Gear.e_defects_action,
dbo.tbl_Lifting_Gear.lift_department_id,
dbo.tbl_Lifting_Gear.lifting_loc
FROM dbo.tbl_equipment
INNER JOIN dbo.tbl_equip_swl_unit
ON dbo.tbl_equipment.e_swl_unit_id = dbo.tbl_equip_swl_unit.unit_id
INNER JOIN dbo.tbl_categories
ON dbo.tbl_equipment.e_cat_id = dbo.tbl_categories.category_id
INNER JOIN dbo.tbl_equip_depts
ON dbo.tbl_equipment.e_department_id = dbo.tbl_equip_depts.dept_id
INNER JOIN dbo.tbl_equip_man
ON dbo.tbl_equipment.e_manafacture_id = dbo.tbl_equip_man.man_id
INNER JOIN dbo.vwSubCategory
ON dbo.tbl_equipment.e_sub_id = dbo.vwSubCategory.category_id
INNER JOIN dbo.vwDescCategory
ON dbo.tbl_equipment.e_cat_id = dbo.vwDescCategory.category_id
INNER JOIN dbo.tbl_Lifting_Gear
ON dbo.tbl_equipment.equipment_id = dbo.tbl_Lifting_Gear.e_id
And here's the select statement with subquery that I am using:
SELECT *
FROM vw_LiftEquip
WHERE lifting_loc = ? AND
con_id = ? AND
EXPR11 =
'N'(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
)
ORDER BY lifting_ref_no,
category_id,
e_swl,
e_serial
I get the error :
Column "vw_LiftEquip.category_id" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Can't see why its returning that error, this is admittedly the first time I've ran a subquery on such a complex view, and I am a bit lost, thanks in advance for any help. I have looked through the similar posts and can find no answers to this one, sorry if I am just being dumb.
You are missing AND between EXPR11 = 'N' and (SELECT MAX(...
Otherwise, it looks OK. MAX without GROUP BY is allowed if you have no other columns in the SELECT
Update: #hvd also noted that you have nothing to compare to MAX(lifting_date). See comment
Update 2,
SELECT *
FROM vw_LiftEquip v1
CROSS JOIN
(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
) v2
WHERE v1.lifting_loc = ? AND
v1.con_id = ? AND
v1.EXPR11 = 'N'
ORDER BY v1.lifting_ref_no,
v1.category_id,
v1.e_swl,
v1.e_serial