Can anyone spot the error with the WITH() clause? - sql

SQL is not recognizing the variable I am calling in the main SELECT statement. The variable I am calling is the execs.block_order_quantity. I name this variable in the WITH statement at the beginning of the query. The code is below, and the error is attached as a picture. I have run the select statement without the WITH execs as( piece and it works just fine.
WITH execs as(SELECT th.exec_id, SUM(eha.tck_ord_qty) as "BLOCK_ORDER_QUANTITY"
FROM t1 eha
join t2 th
on eha.exec_id = th.exec_id
where th.trdng_desk_sname IN ('NAME')
and th.trd_dt between to_date('201840101', 'YYYYMMDD')
and to_date ('20140301', 'YYYYMMDD')
and exists
(SELECT 1
FROM t2t eth
WHERE eth.TRD_ID = eha.TRD_ID
AND eth.trd_stat_cd = 'EX')
group by th.exec_id)
SELECT DISTINCT
th.trd_dt as "TRADE_DATE",
eah.ord_cap_qty as "CAP_AMOUNT",
execs.block_order_quantity as "BLOCK_ORDER_QUANTITY",
eah.alloc_ovrrd_rsn_cd as "ALLOC_OVRRD_RSN_CD",
CASE --create allocation case id
WHEN(eh.manl_alloc_ind = 'Y'
OR NVL (eah.trdr_drct_qty, 0) > 0
OR NVL (eah.trdr_drct_wgt_ratio, 0) > 0)
THEN
'Y'
ELSE
'N'
END
AS "ALLOCATION_OVRRD_IND",
CASE
WHEN (eh.manl_alloc_ind = 'Y'
OR NVL (eah.trdr_drct_qty, 0) > 0
OR NVL (eah.trdr_drct_wgt_ratio, 0) > 0)
THEN
TH.EXEC_TMSTMP
ELSE
NULL
END
AS "ALLOCATION_OVRRD_TIMESTAMP",
eah.alloc_adj_assets_rt_curr_amt as "FUND_ADJ_NET_ASSETS",
eah.as_alloc_exec_hld_qty as "FUND_HOLDINGS_QUANTITY",
th.as_trd_iv_lname as "SECURITY_NAME",
th.as_trd_fmr_ticker_symb_cd as "TICKER",
CASE
WHEN NVL(th.limit_prc_amt, 0) > 0 THEN 'LIMIT' ELSE NULL END
AS "FUND_ORDER_TYPE"
from t1 eah
join t3 eh
on eah.exec_id = eah.exec_id
join t2 th
on th.trd_id = eah.trd_id
join t4 tk
on tk.tck_id = eah.tck_id
join t5 pm
on eah.pm_person_id_src = pm.person_id_src
where th.trdng_desk_sname IN('NAME')
and th.trd_dt between to_date('20140101', 'YYYYMMDD')
and to_date ('20140301', 'YYYYMMDD')
and rownum < 15

You need to join to the execs common table expression (CTE) name in your main query, e.g.:
...
from t1 eah
join t3 eh
on eah.exec_id = eah.exec_id
join t2 th
on th.trd_id = eah.trd_id
join execs
on execs.exec_id = eh.exec_id
join t4 tk
...
I'm not sure you actually want a CTE here, it looks like you could just do the aggregation in the main query as you're referencing the same tables; but there may be something I'm missing, like duplicates introduced by later joins.
Incidentally, the first on clause there looks wrong, as both sides refer to the same column in the same table; so it should probably be:
...
from t1 eah
join t3 eh
on eh.exec_id = eah.exec_id
join t2 th
Having distinct is sometimes a sign that there joins aren't right and there are duplicates you want to suppress which shouldn't really be there, so you may not need that once the join condition is fixed; and that might allow a simple aggregate to work too if it was giving the wrong result before. (Or there could stil be some other reason it's not appropriate.)
Also, the where rownum < 15 will give an indeterminate set of rows as you aren't ordering the result set before applying that filter.

Related

Attempting to use result of Case Expression in a join .. need to improve query

I have the following query which allows me to join the TransactionClass tables base on TransactionClassID from either the primary table (Transactions) or TransactionRules based on a condition as below:
SELECT
Description,
TC.Name,
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END) As ClassId
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId =
(CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionClassId
ELSE T.TransactionClassId
END)
The query is running on SQL Server,
In effect, it retrieves the correct TransactionClass entry depending on whether or not the join on TransactionRules was successful or not.
The above query works, but I am trying to simplify the query so that I do not have to repeat the CASE expression in two places.
I attempted to capture the result of the case expression in a variable and use that as follows:
SELECT
Description,
x
FROM Transactions AS T
LEFT JOIN TransactionRules TR
ON T.Description LIKE TR.Pattern
LEFT JOIN TransactionClasses TC
ON TC.TransactionClassId = x
WHERE x = (CASE
WHEN (TR.TransactionRuleId > 0)
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END)
But I get the error:
[S0001][207] Line 8: Invalid column name 'x'.
Where am I going wrong in my attempt to have only one CASE Expression?
CROSS APPLY is a tidy way to reuse a calculated value e.g.
SELECT
[Description]
, TC.[Name]
, Class.Id
FROM Transactions AS T
LEFT JOIN TransactionRules TR ON T.[Description] LIKE TR.Pattern
CROSS APPLY (
VALUES (
CASE
WHEN TR.TransactionRuleId > 0
THEN TR.TransactionRuleId
ELSE T.TransactionClassId
END
)
) AS Class (Id)
LEFT JOIN TransactionClasses TC ON TC.TransactionClassId = Class.Id;

How could I join these queries together?

I have 2 queries. One includes a subquery and the other is a pretty basic query. I can't figure out how to combine them to return a table with name, workdate, minutes_inactive, and hoursworked.
I have the code below for what I have tried. The simple query is lines 1,2, and the last 5 lines. I also added a join clause (join punchclock p on p.servrepID = l.repid) to it.
Both these queries ran on their own so this is solely just the problem of combining them.
select
sr.sr_name as liaison, cast(date_created as date) workdate,
(count(date_created) * 4) as minutes_inactive,
(select
sr_name, cast(punchintime as date) as workdate,
round(sum(cast(datediff(minute,punchintime, punchouttime) as real) / 60), 2) as hoursworked,
count(*) as punches
from
(select
sr_name, punchintime = punchdatetime,
punchouttime = isnull((select top 1 pc2.punchdatetime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime), getdate())
from
punchclock pc
join
servicereps sr on pc.servrepid = sr.servrepid
where
punchyear >= 2017 and pc.inout = 1
group by
sr_name, cast(punchintime as date)))
from
tbl_liga_popup_log l
join
servicereps sr on sr.servrepID = l.repid
join
punchclock p on p.servrepID = l.repid collate latin1_general_bin
group by
cast(l.date_created as date), sr.sr_name
I get this error:
Msg 102, Level 15, State 1, Line 19
Incorrect syntax near ')'
I keep getting this error but there are more errors if I adjust that part.
I don't know that we'll fix everything here, but there are a few issues with your query.
You have to alias your sub-query (technically a derived table, but whatever)
You have two froms in your outer query.
You have to join to the derived table.
Here's an crude example:
select
<some stuff>
from
(select col1 from table1) t1
inner join t2
on t1.col1 = t2.col2
The large error here is that you are placing queries in the select section (before the from). You can only do this if the query returns a single value. Else, you have to put your query in a parenthesis (you have done this) in the from section, give it an alias, and join it accordingly.
You also seem to be using group bys that are not needed anywhere. I can't see aggregation functions like sum().
My best bet is that you are looking for the following query:
select
sr_name as liaison
,cast(date_created as date) workdate
,count(distinct date_created) * 4 as minutes_inactive
,cast(punchintime as date) as workdate
,round(sum(cast(datediff(minute,punchintime,isnull(pc2_query.punchouttime,getdate())) as real) / 60), 2) as hoursworked
,count(*) as punches
from
punchclock pc
inner join servicereps sr on pc.servrepid = sr.servrepid
cross apply
(
select top 1 pc2.punchdatetime as punchouttime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime
)q1
inner join tbl_liga_popup_log l on sr.servrepID = l.repid
where punchyear >= 2017 and pc.inout = 1

How can I refactor this query

How can I rewrite this SQL code? I would like to avoid the repetitive execution of the case for every record.
SELECT chcr.chsid,
CASE
WHEN EXISTS
(SELECT 1
FROM hdr_run chre,
clmerr ce
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
AND chre.clm_error_sid = ce.clm_error_sid
GROUP BY chre.chsid
HAVING COUNT(chre.clm_error_sid) > 0
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr,
clm_der chde
WHERE chde.chsid = chcr.chsid
Have a look at that query please:
SELECT
chcr.chsid,
CASE
WHEN ce.clm_error_sid IS NOT NULL AND COUNT(chre.clm_error_sid, 0) > 0
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr
JOIN clm_der chde ON chde.chsid = chcr.chsid
LEFT JOIN hdr_run chre ON chre.chsid = chcr.chsid AND chre.run_nmbr < chcr.last_run_nmbr
LEFT JOIN clmerr ce ON chre.clm_error_sid = ce.clm_error_sid
GROUP BY chcr.chsid
If there's more than one clm_der for each clm_res based on their chsid, we'd have to double check that the COUNT is not counting the extras from clm_der.
I have no data to test this on so all I can go on is the SQL you've provided but from a brief look it does not appear that the GROUP BY and HAVING COUNT() > 0 statements are required as the combination of the INNER JOIN condition in the sub-query and the use of EXISTS in the outer query does the same thing.
Does this have exactly the same functionality:
SELECT chcr.chsid,
CASE
WHEN EXISTS
( SELECT 1
FROM hdr_run chre
INNER JOIN
clmerr ce
ON (chre.clm_error_sid = ce.clm_error_sid)
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM clm_res chcr
INNER JOIN
clm_der chde
ON ( chde.chsid = chcr.chsid );
SQLFIDDLE
Also, repeated execution of the CASE statement is not a bad thing as the optimizer should not duplicate executions of the sub-query.

SQL Server query with CASE and GROUP BY, field invalid?

Can't figure out what I'm doing wrong here. It says field HasNoteDate is invalid. I just want it to return 1 if there's a date, 0 if there's not and I wanted it grouped so I can get the counts and the sum of loan amounts. I've looked at the stackoverflow answers for grouping by a case and none of them are solving it for me. Thanks!
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.LOAN_AMT, dbo.LOAN.DEAL_STATUS, HasNoteDate
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
logic of SQL query execution is not straightforward as common programming languages
here are sample execution stages for your query:
perform join on tables in FROM CLAUSE
perform GROUP BY - this will cause error, as HasNoteDate is not defined for this moment
perform ORDER BY
perform SELECT - only during this stage column HasNoteDate is defined
so, you cannot use undefined column HasNoteDate in GROUP BY, you have to replace it with your statement (CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL THEN 0 ELSE 1 END), then sql server will be able to GROUP
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
Use columns in your group by exactly the way you have defined in you select Statement, otherwise SQL server tries to GROUP it with the fields that it cannot find in SELECT statement and throws an error.

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