I have a SQL query that is giving me this error.
Column INSTR.JOB_HDR.JOB_START_DTTM is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
But... I am using an aggregate, here is my query
SELECT [JOB_NAME]
, [JOB_DESCR]
, [INFA_FOLDER_NAME]
, [WORKFLOW_NAME]
, [LOAD_GROUP]
, MAX(JOB_START_DTTM) AS 'JOB START'
, MAX(JOB_END_DTTM) AS 'JOB END'
, [JOB_STATUS]
FROM [INSTR].[JOB] JB
INNER JOIN [INSTR].[JOB_HDR] JOB_HDR
ON JB.JOB_ID = JOB_HDR.JOB_ID
WHERE (JB.JOB_NAME LIKE 'EDW%1D00%')
AND
(
(JOB_STATUS = 'COMPLETE')
OR (JOB_STATUS = 'RUNNING')
)
GROUP BY JOB_NAME
, JOB_DESCR
, INFA_FOLDER_NAME
, WORKFLOW_NAME
, LOAD_GROUP
, JOB_STATUS
ORDER BY JOB_HDR.JOB_START_DTTM DESC
, JOB_HDR.JOB_END_DTTM DESC;
Funny enough, just to see, I put those columns in the group by and I get results. But the results are giving me multiple records, when I just want the highest value for the job start and end times which is why I used max.
In case it helps, this is the format of the record for job start and end.
2023-02-08 16:12:09.
What is causing the order by clause to not know that I'm using the max function?? Why is the max function not working?
I'm doing this as a test run. I work in a baby IT JOB that allows you to learn SQL while working. And then you do a "Qual book" checkout. My signatory gave me the hint to use an aggregate function to those. I suggested max and they more less confirmed without giving me the answer, cause I'm supposed to write this query on my own.
But also, he mentioned I would use a case statement for the job status (which confuses me because my where clause filters what I want already) how would a case statement? I'm not as familiar with CASE as I'd like to be and all the free resources don't seem to be making it click for me.
Thanks for any help! I mostly just really want to know the why of problem, why is my aggregate function not working....
The results are to pull those columns in the select, using aforementioned join for two tables.
The results need to show job status as "running" or "complete" with the latest run time (job start, end time). This should produce 1 unique record for each "job name" with %edw%1d00% cause I want only the latest run time and it's status.
Hope this clarifies.
Try this:
SELECT [JOB_NAME]
, [JOB_DESCR]
, [INFA_FOLDER_NAME]
, [WORKFLOW_NAME]
, [LOAD_GROUP]
, MAX(JOB_START_DTTM) AS 'JOB START'
, MAX(JOB_END_DTTM) AS 'JOB END'
, [JOB_STATUS]
FROM [INSTR].[JOB] JB
INNER JOIN [INSTR].[JOB_HDR] JOB_HDR
ON JB.JOB_ID = JOB_HDR.JOB_ID
WHERE (JB.JOB_NAME LIKE 'EDW%1D00%')
AND
(
(JOB_STATUS = 'COMPLETE')
OR (JOB_STATUS = 'RUNNING')
)
GROUP BY [JOB_NAME]
, [JOB_DESCR]
, [INFA_FOLDER_NAME]
, [WORKFLOW_NAME]
, [LOAD_GROUP]
, [JOB_STATUS]
ORDER BY MAX(JOB_HDR.JOB_START_DTTM) DESC
, MAX(JOB_HDR.JOB_END_DTTM) DESC;
The issue is that your order by was trying to order by things that aren't in the group by, or being aggregated, like the error mentions. The way to fix that in this case is to aggregate them in the order by
Related
Apologies in advance for what will probably be a very stupid question but I've been using Google to teach myself SQL after making the move from years of using Crystal Reports.
We have Works Orders which can have numerous transactions against them. I want to find the most recent one and have it returned against the Works Order number (which is a unique ID)? I attempted to use MAX but that just returns whatever the Transaction Date for that record is.
I think my struggles may be caused by a lack of understanding of grouping in SQL. In Crystal it was just 'choose what to group by' but for some reason in SQL I seem to be forced to group by all selected fields.
My ultimate goal is to be able to compare the planned end date of the Works Order ("we need to finish this job by then") vs when the last transaction was booked against the Works Order, so that I can create an OTIF KPI.
I've attached an image of what I'm currently seeing in SQL Server 2014 Management Studio and below is my attempt at the query.
SELECT wip.WO.WO_No
, wip.WO.WO_Type
, stock.Stock_Trans_Log.Part_No
, stock.Stock_Trans_Types.Description
, stock.Stock_Trans_Log.Qty_Change
, stock.Stock_Trans_Log.Trans_Date
, wip.WO.End_Date
, wip.WO.Qty - wip.WO.Qty_Stored AS 'Qty remaining'
, MAX(stock.Stock_Trans_Log.Trans_Date) AS 'Last Production Receipt'
FROM stock.Stock_Trans_Log
INNER JOIN production.Part
ON stock.Stock_Trans_Log.Part_No = production.Part.Part_No
INNER JOIN wip.WO
ON stock.Stock_Trans_Log.WO_No = wip.WO.WO_No
INNER JOIN stock.Stock_Trans_Types
ON stock.Stock_Trans_Log.Tran_Type = stock.Stock_Trans_Types.Type
WHERE (stock.Stock_Trans_Types.Type = 10)
AND (stock.Stock_Trans_Log.Store_Code <> 'BI')
GROUP BY wip.WO.WO_No
, wip.WO.WO_Type
, stock.Stock_Trans_Log.Part_No
, stock.Stock_Trans_Types.Description
, stock.Stock_Trans_Log.Qty_Change
, stock.Stock_Trans_Log.Trans_Date
, wip.WO.End_Date
, wip.WO.Qty - wip.WO.Qty_Stored
HAVING (stock.Stock_Trans_Log.Part_No BETWEEN N'2Z' AND N'9A')
Query + results
If my paraphrase is correct, you could use something along the following lines...
WITH
sequenced_filtered_stock_trans_log AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY WO_No
ORDER BY Trans_Date DESC) AS reversed_sequence_id
FROM
stock.Stock_Trans_Log
WHERE
Type = 10
AND Store_Code <> 'BI'
AND Part_No BETWEEN N'2Z' AND N'9A'
)
SELECT
<stuff>
FROM
sequenced_filtered_stock_trans_log AS stock_trans_log
INNER JOIN
<your joins>
WHERE
stock_trans_log.reversed_sequence_id = 1
First, this will apply the WHERE clause to filter the log table.
After the WHERE clause is applied, a sequence id is calculated. Restarting from one for each partition (each WO_No), and starting from the highest Trans_Date.
Finally, that can be used in your outer query with a WHERE clause that specifies that you only want the records with sequence id one, this it the most recent row per WO_No. The rest of the joins on to that table would proceed as normal.
If there is any other filtering that should be done (through joins or any other means) that should all be done before the application of the ROW_NUMBER().
I found this query in an MS Access database that was built by someone else:
SELECT
tblWorkOrder.WorkOrderNum
, tblWorkOrder.SprayTypes
, tblWorkOrder.Description
, tblWorkOrderMaterials.ChemicalName
, tblWorkOrderMaterials.RatePerAcre
, tblMaterials.ApplicationUnit
, tblMaterials.DryOrLiquid
, tblWorkOrderMaterials.ID
FROM (tblMaterials
INNER JOIN tblMaterialsDetails ON tblMaterials.ChemicalName = tblMaterialsDetails.ChemicalName)
INNER JOIN (tblWorkOrder
INNER JOIN tblWorkOrderMaterials ON tblWorkOrder.WorkOrderNum = tblWorkOrderMaterials.WorkOrderNum) ON tblMaterials.ChemicalName = tblWorkOrderMaterials.ChemicalName
WHERE (((tblMaterialsDetails.CropType) = "Apples"
OR (tblMaterialsDetails.CropType) = "All"))
GROUP BY
tblWorkOrder.WorkOrderNum
, tblWorkOrder.Description
, tblWorkOrderMaterials.ChemicalName
, tblWorkOrderMaterials.RatePerAcre
, tblMaterials.ApplicationUnit
, tblMaterials.DryOrLiquid
, tblWorkOrderMaterials.ID;
The query runs fine in Access, which is the problem. How does this query run when field "tblWorkOrder.SprayTypes" is included in the SELECT list but not in the GROUP BY clause? It should cause an error based on the field not being included in the aggregate function, right? When I migrated the back end to MySQL, it broke like I would expect it to so I want to make sure I wasn't missing something in the Access back end version.
Here is the relationship between tblWorkOrder and tblSprayTypes:
It runs successfully because there is nothing in the select clause that necessitates a group by clause. There is no min, max, sum, count, or avg.
The point of the group by clause is not clear, but that wasn't your question.
I am getting this error:
Msg 8120, Level 16, State 1, Procedure ReportEmployeesOnLeave, Line 17
Column 'Employee.EmployeeId' is invalid in the select list because it
is not contained in either an aggregate function or the GROUP BY
clause.
What about the error message don't you understand? It's pretty self-explanatory. What it means is: If you use a group by, all the selected attributes have to be either in the group by or in an aggregate function (COUNT(), SUM() etc.).
So, if you correct your group by you shouldn't have any errors:
...
GROUP BY TC.Date
, TC.DayName
, TC.DayType
, TC.ScheduleId
, TC.LeaveTaken
, TC.Remarks
, E.EmployeeId
, E.EmployeeNo
, E.Name
, E.ScheduleId
, C.BusinessName
Whether this gives the result you're looking for, is another question.
For future questions: Please add code as text, not as a picture. That way answerers can simply copy-paste, rather than typing it all over.
edit: If you don't want to group by all of your selected attributes you can use window functions (assuming sql server 2012 or above):
SELECT * -- Everything you need
, COUNT(TC.AbsentCalculation) OVER(PARTITION BY E.Name, E.EmployeeId) AS AbsentCount
, SUM(TC.AbsentCalculation) OVER(PARTITION BY E.Name, E.EmployeeId) AS TotalAbsents
FROM ...
You won't need a GROUP BY at all if you implement this.
Write all the fields into Group By cause
I currently have some SQL code which looks like this.
SELECT
WORKORDER_BASE_ID As 'Work Order',
SCHED_START_DATE AS 'Scheduled Start',
SETUP_HRS AS 'Approx Setup Hrs',
RUN_HRS AS 'Approx Run Hrs',
(
SELECT
PART_ID as "Components"
FROM
REQUIREMENT
WHERE
REQUIREMENT.WORKORDER_BASE_ID = OPERATION.WORKORDER_BASE_ID
AND REQUIREMENT.WORKORDER_SUB_ID = OPERATION.WORKORDER_SUB_ID
AND PART_ID LIKE '%PSU%'
) AS PSU
FROM
OPERATION
WHERE
OPERATION.STATUS = 'R'
AND RESOURCE_ID LIKE '%{Root Container.equipmentName}%'
I am receiving errors because the sub-query generates more than one field. What I need is a way to specify a condition to the sub-query to only display data pertaining to a the specific work order in that row, specifically the work order number. I'm guessing this is some sort of loop function.
Any suggestions?
BTW, the bottom line is correct. The platform I use interprets values in braces as local variables.
A Sub-Query in select MUST return a scalar value. Use TOP 1 in your select and it should fix the issue. Or Alternately you can do the following ....
SELECT OPERATION.WORKORDER_BASE_ID AS [Work Order]
,OPERATION.SCHED_START_DATE AS [Scheduled Start]
,OPERATION.SETUP_HRS AS [Approx Setup Hrs]
,OPERATION.RUN_HRS AS [Approx Run Hrs]
,REQUIREMENT.PART_ID AS [Components]
FROM OPERATION
INNER JOIN REQUIREMENT ON REQUIREMENT.WORKORDER_BASE_ID = OPERATION.WORKORDER_BASE_ID
AND REQUIREMENT.WORKORDER_SUB_ID = OPERATION.WORKORDER_SUB_ID
WHERE OPERATION.[STATUS] ='R'
AND OPERATION.RESOURCE_ID LIKE '%{Root Container.equipmentName}%'
AND REQUIREMENT.PART_ID LIKE '%PSU%'
I have a (join) query that works as expected. But as soon as I add the following column, it does not show any results nor does it complete. (Query running counter keeps growing)
IF((d.network_type contains '_user' AND d.is_network=1),s.impressions,0) AS effimp
Is there any other way to optimize this?
The full query is as follows and it was working when I tried it in the last month.
SELECT s.date_time AS date_time
, s.requests AS requests, s.impressions AS impressions
, s.clicks AS clicks, s.conversions AS conversions
, IF((d.network_type contains '_user'
AND d.is_network=1),s.impressions,0) AS effimp
, s.total_revenue AS total_revenue
, s.total_basket_value AS total_basket_value
, s.total_num_items AS total_num_items
, s.zone_id as zone_id
FROM company.ox_data_summary s
INNER JOIN company.ox_banners1 AS d ON d.bannerid=s.ad_id
limit 100
Query Failed
Error: Unexpected. Please try again.
If I remove the "IF clause it does work.
Looks like you're hitting a query processing bug. We're investigating.