Firebird: sum of the multiplication of two fields within a select statement - sql

Basically what I need is to get the sum of the multiplication of two fields.
For example: SUM ((field_1 or field_2) * field_3)
But field_1 or field_2 are selected based on the value of a fourth field, field_4
My table:
field_1: Float
field_2: Float
field_3: Float
field_4: Char
In short, what i need is something like this:
SELECT
...
IF field_4 = 'K'
THEN
SUM( field_1 * field_3 )
ELSE
SUM( field_2 * field_3 )
I tried with IF and CASE statements, but i can't make it work.
Here my real query:
SELECT
D.id,
D.name,
SUM(CASE WHEN D.sale_unity = 'K'
THEN (D.cost_price * CI.quantity_k)
ELSE (D.cost_price * CI.quantity_u) ) AS total_cost,
SUM(CASE WHEN D.sale_unity = 'K'
THEN (D.sale_price * CI.quantity_k)
ELSE (D.sale_price * CI.quantity_u) ) AS net
FROM DETAIL D
INNER JOIN VOUCHER AS V ON V.id = D.voucher_id
WHERE V.client_id = 97 AND V.date BETWEEN '06/01/2012' AND '07/01/2012'
GROUP BY D.id, D.name

I think that what is wrong on your query is that your CASE statement is missing the END. Try this:
SELECT
D.id,
D.name,
SUM(CASE WHEN D.sale_unity = 'K'
THEN (D.cost_price * CI.quantity_k)
ELSE (D.cost_price * CI.quantity_u) END ) AS total_cost,
SUM(CASE WHEN D.sale_unity = 'K'
THEN (D.sale_price * CI.quantity_k)
ELSE (D.sale_price * CI.quantity_u) END ) AS net
FROM DETAIL D
INNER JOIN VOUCHER AS V ON V.id = D.voucher_id
WHERE V.client_id = 97 AND V.date BETWEEN '06/01/2012' AND '07/01/2012'
GROUP BY D.id, D.name

Related

Divide the results of two select queries

I have two SQL count queries that on their own work fine, they are:
SELECT count(*) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
RESULT: TOTAL_PROGRESS_BY_LINE_ = 26
SELECT count(*) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
RESULT: TOTAL_LINES_BY_PROJECT_ = 130
Now how to do I add to the query to get the percentage of 26/130??
I have a new query to go along with how to get percentages.
Here it is:
SELECT ISOGEN_LINE_PROGRESS_, PROJECT_NUMBER_,
CASE
WHEN ISOGEN_LINE_PROGRESS_ = 'A' THEN 'NOT IN MODEL'
WHEN ISOGEN_LINE_PROGRESS_ = 'B' THEN 'ROUGHED IN'
WHEN ISOGEN_LINE_PROGRESS_ = 'C' THEN 'PARTIAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'D' THEN 'READY FOR FINAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'E' THEN '100% COMPLETE'
WHEN ISOGEN_LINE_PROGRESS_ = '0' THEN 'ISSUE FOR CONSTRUCTION'
END AS PROGRESS_PER_LINE_
FROM PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
ORDER BY ISOGEN_LINE_PROGRESS_
this brings back results below:
ISOGEN_LINE_PROGRESS_ PROJECT_NUMBER_ PROGRESS_PER_LINE_
A PJ001234 NOT IN MODEL
B PJ001234 ROUGHED IN
C PJ001234 PARTIAL CHECK
D PJ001234 READY FOR FINAL CHECK
If I remove the Distinct from my query there are obviously multiple rows for each level of progress. How do I add to the above distinct query to have a column at the end with the rate or percent of each level of progress compared to the overall number of lines?
Select them as a subquery.
By default the result will be an integer because count(*) returns an int. For a decimal result convert to a decimal.
SELECT (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
) / (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
)
You may use conditional aggregation and simple division in one query:
select
100.0 *
count(
case when ISOGEN_LINE_PROGRESS_ = 'C'
then 1
end
)
/
nullif(count(
case when PROJECT_NUMBER_ = 'PJ001234'
then 1
end
), 0) as rate_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
or PROJECT_NUMBER_ = 'PJ001234'
DECLARE #firstone INT;
DECLARE #secondone INT;
SELECT #firstone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C';
SELECT #secondone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234';
SELECT #firstone / #secondone AS resultthing
SELECT #firstone /CAST(#secondone AS DECIMAL (9,2))
You could use a common table expression to get the counts and then select the desired results in one swell foop:
with Counts as (
select
( select Count(*) from Sys.Tables ) as NumberOfTables,
( select Count(*) from Sys.Columns ) as NumberOfColumns
)
select NumberOfTables, NumberOfColumns,
NumberOfColumns / NumberOfTables as ColumnsPerTable,
( 100 * NumberOfColumns ) / NumberOfTables as IntegerPercentColumnsPerTable,
( 100.0 * NumberOfColumns ) / NumberOfTables as NumericPercentColumnsPerTable
from Counts;
I used existing tables since you chose not to supply DDL and sample data. So it goes.

how to use case with group by?

the query works well but when iam adding group by it gives me [Error] ORA-01427 here is the main query
SELECT DISTINCT Contract_number,
area_number,
area_name,
ADVANCE_PAY,
Postponed_Amount,
extract_number,
total
FROM (SELECT xxr.Contract_num Contract_number,
xxr.p_area_no area_number,
xxr.p_area_name area_name,
xxr.ADVANCE_PAY ADVANCE_PAY,
xxr.DEFERRED_BOOST Postponed_Amount,
xxr.release_num extract_number,
and here is the case statement :
(SELECT DISTINCT
CASE
WHEN :p_item_code IS NOT NULL
THEN
TOTAL_AMOUNT
WHEN :p_item_code IS NULL
THEN
( (SELECT NVL (SUM (TOTAL_AMOUNT), 0)
FROM XXEXTRACT.XXNATGAS_REALSES_LINES
WHERE XXEXTRACT.XXNATGAS_REALSES.release_id =
XXEXTRACT.XXNATGAS_REALSES_LINES.release_id))
ELSE
NULL
END
FROM XXEXTRACT.XXNATGAS_REALSES_LINES xxrl,
XXEXTRACT.XXNATGAS_REALSES
WHERE 1 = 1
AND xxrl.release_id =
XXEXTRACT.XXNATGAS_REALSES.release_id)
AS total
and here is the from part :
FROM XXEXTRACT.XXNATGAS_REALSES_LINES xxrl,
XXEXTRACT.XXNATGAS_REALSES xxr
WHERE 1 = 1
AND xxrl.release_id = xxr.release_id
AND xxr.release_date >= NVL (:p_date_from, xxr.release_date)
AND xxr.release_date <= NVL (:p_date_to, xxr.release_date)
AND xxr.Contract_num = NVL (:p_cont_num, xxr.Contract_num)
AND xxr.vendor_id = NVL (:p_ven_id, xxr.vendor_id)
AND xxr.vendor_site_id = NVL (:p_site_id, xxr.vendor_site_id)
)
and here is the group by :
GROUP BY Contract_number,
area_number,
area_name,
ADVANCE_PAY,
Postponed_Amount,
extract_number,
total;
these is the full query so please any help
For sure I couldn't understand very well your query. You could improve your post for next time.
As answer, I think you should encapsulate your select statment and group by using your select as subquery. It is not the best approach but it may works fine.
select *
from (
select distinct Contract_number
,area_number
,area_name
,ADVANCE_PAY
,Postponed_Amount
,extract_number
,total
from (
select xxr.Contract_num Contract_number
,xxr.p_area_no area_number
,xxr.p_area_name area_name
,xxr.ADVANCE_PAY ADVANCE_PAY
,xxr.DEFERRED_BOOST Postponed_Amount
,xxr.release_num extract_number
,(
select distinct case
when :p_item_code is not null
then TOTAL_AMOUNT
when :p_item_code is null
then (
(
select NVL(SUM(TOTAL_AMOUNT), 0)
from XXEXTRACT.XXNATGAS_REALSES_LINES
where XXEXTRACT.XXNATGAS_REALSES.release_id = XXEXTRACT.XXNATGAS_REALSES_LINES.release_id
)
)
else null
end
from XXEXTRACT.XXNATGAS_REALSES_LINES xxrl
,XXEXTRACT.XXNATGAS_REALSES
where 1 = 1
and xxrl.release_id = XXEXTRACT.XXNATGAS_REALSES.release_id
) as total
from XXEXTRACT.XXNATGAS_REALSES_LINES xxrl
,XXEXTRACT.XXNATGAS_REALSES xxr
where 1 = 1
and xxrl.release_id = xxr.release_id
and xxr.release_date >= NVL(:p_date_from, xxr.release_date)
and xxr.release_date <= NVL(:p_date_to, xxr.release_date)
and xxr.Contract_num = NVL(:p_cont_num, xxr.Contract_num)
and xxr.vendor_id = NVL(:p_ven_id, xxr.vendor_id)
and xxr.vendor_site_id = NVL(:p_site_id, xxr.vendor_site_id)
)
) TBL1
group by TBL1.Contract_number
,TBL1.area_number
,TBL1.area_name
,TBL1.ADVANCE_PAY
,TBL1.Postponed_Amount
,TBL1.extract_number
,TBL1.total;

How to add a count/sum and group by in a CTE

Just a question on displaying a row on flight level and displaying a count on how many crew members on that flight.
I want to change the output so it will only display a single record at flight level and it will display two additional columns. One column (cabincrew) is the count of crew members that have the 'CREWTYPE' = 'F' and the other column (cockpitcrew) is the count of crew members that have the `'CREWTYPE' = 'C'.
So the query result should look like:
Flight DepartureDate DepartureAirport CREWBASE CockpitCrew CabinCrew
LS361 2016-05-19 BFS BFS 0 3
Can I have a little help tweaking the below query please:
WITH CTE AS (
SELECT cd.*, c.*, l.Carrier, l.FlightNumber, l.Suffix, l.ScheduledDepartureDate, l.ScheduledDepartureAirport
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY LegKey ORDER BY UpdateID DESC) AS RowNumber FROM Data.Crew) c
INNER JOIN
Data.CrewDetail cd
ON c.UpdateID = cd.CrewUpdateID
AND cd.IsPassive = 0
AND RowNumber = 1
INNER JOIN
Data.Leg l
ON c.LegKey = l.LegKey
)
SELECT
sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix AS Flight
, sac.DepartureDate
, sac.DepartureAirport
, sac.CREWBASE
, sac.CREWTYPE
, sac.EMPNO
, sac.FIRSTNAME
, sac.LASTNAME
, sac.SEX
FROM
Staging.SabreAssignedCrew sac
LEFT JOIN CTE cte
ON sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix = cte.Carrier + CAST(cte.FlightNumber AS VARCHAR) + cte.Suffix
AND sac.DepartureDate = cte.ScheduledDepartureDate
PLEASE TRY THIS.
SELECT Flight,
DepartureDate,
DepartureAirport,
CREWBASE,
SUM(CASE WHEN CREWTYPE = 'F' THEN 1 ELSE 0 END) AS CabinCrew ,
SUM(CASE WHEN CREWTYPE = 'C' THEN 1 ELSE 0 END) AS CockpitCrew
FROM #Table
GROUP BY Flight, DepartureDate, DepartureAirport, CREWBASE
Please Try This:
select Flight, DepartureDate, DepartureAirport,CREWBASE,
count(case when CREWTYPE='F' then 1 end ) as CabinCrew,count(case when CREWTYPE='C' then 1 end ) as CockpitCrew
from Staging.SabreAssignedCrew
group by Flight, DepartureDate, DepartureAirport,CREWBASE

SQL Query is taking to long to excecute

I have the below query that is taking too long:
{SELECT /*+ PARALLEL(5) */
EXTER.ACE_IT_REGION_ID ,
EXTER.ACE_IT_LOCATION_CODE,
EXTER.ACE_IT_ORD_NUM,
EXTER.TOTAL_ITEM_PRICE_PER_ORDER,
EXTER.TOTAL_ACE_PAYD_AMOUNT,
EXTER.ACE_ORD_COMPLETION_TIME AS DATEOFDATA
FROM
(SELECT /*+ use_hash(TAB1,TAB2) +*/
DISTINCT
TAB1.ACE_IT_REGION_ID ,
TAB1.ACE_IT_LOCATION_CODE,
TAB1.ACE_IT_ORD_NUM,
TAB1.TOTAL_ITEM_PRICE_PER_ORDER,
TAB2.TOTAL_ACE_PAYD_AMOUNT,
TAB1.ACE_ORD_COMPLETION_TIME
FROM
(SELECT AAA.ACE_IT_REGION_ID,
AAA.ACE_IT_LOCATION_CODE,
AAA.ACE_IT_ORD_NUM,
AAA.SUM_PRICE_PLUS_TAX,
AAA.TOTAL_DISCOUNT,
(AAA.SUM_PRICE_PLUS_TAX-AAA.TOTAL_DISCOUNT) AS TOTAL_ITEM_PRICE_PER_ORDER,
TRUNC(AAA.ACE_ORD_COMPLETION_TIME)
FROM (SELECT B.ACE_IT_REGION_ID AS ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE AS ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM AS ACE_IT_ORD_NUM,
(SUM(B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT)*B.ACE_IT_QTY) AS SUM_PRICE_PLUS_TAX,
SUM(B.ACE_IT_DISC_AMT+B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT,
TRUNC(A.ACE_ORD_COMPLETION_TIME ) AS ACE_ORD_COMPLETION_TIME
FROM POSDB.ACE_ORDERS A, POSDB.ACE_ITEM_TRAN B
WHERE A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1)
AND A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE)
AND A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID
AND A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE
AND A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM
AND A.ACE_ORD_TYPE = 'IS'
AND (A.ACE_ORD_STATUS = 'CR'
OR A.ACE_ORD_STATUS IS NULL
OR A.ACE_ORD_STATUS LIKE ' %'
OR A.ACE_ORD_STATUS LIKE '% ')
AND (B.ACE_IT_VOID_IND <> 'V' OR B.ACE_IT_VOID_IND IS NULL )
GROUP BY B.ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM,
A.ACE_ORD_COMPLETION_TIME) AAA
ORDER BY AAA.ACE_IT_REGION_ID,
AAA.ACE_IT_LOCATION_CODE,
AAA.ACE_IT_ORD_NUM,
AAA.ACE_ORD_COMPLETION_TIME) TAB1,
(SELECT ACE_PAYD_REGION_ID,
ACE_PAYD_LOCATION_CODE,
ACE_PAYD_ORD_NUM,
SUM(ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT
FROM POSDB.ACE_PAYMENT_DTL
WHERE ACE_PAYD_POSTING_TIMESTAMP BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE)
AND (ACE_PAYD_STATUS <> 'V' OR ACE_PAYD_STATUS IS NULL )
GROUP BY
ACE_PAYD_REGION_ID,
ACE_PAYD_LOCATION_CODE,
ACE_PAYD_ORD_NUM) TAB2
WHERE TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID
AND TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE
AND TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM
ORDER BY
TAB1.ACE_IT_REGION_ID ,
TAB1.ACE_IT_LOCATION_CODE,
TAB1.ACE_IT_ORD_NUM ) EXTER
WHERE (EXTER.TOTAL_ITEM_PRICE_PER_ORDER = EXTER.TOTAL_ACE_PAYD_AMOUNT)
AND EXTER.ACE_ORD_COMPLETION_TIME IS NOT NULL;}
Please give me any suggestions. I have used hints but still not sure why it's taking so much time.
All the tables are huge, about 300,000,000 each.
Before joining the table in tab3 temp table it was taking 5 mins...but now even after 20-25 min it does not return records.
slightly cleaned-up for readability of each being subset of next level down. Also removed the redundant outer query and just added it's WHERE clause to the one inside. Should be same result
SELECT DISTINCT *
FROM
( SELECT
AAA.ACE_IT_REGION_ID,
AAA.ACE_IT_LOCATION_CODE,
AAA.ACE_IT_ORD_NUM,
AAA.SUM_PRICE_PLUS_TAX,
AAA.TOTAL_DISCOUNT,
AAA.SUM_PRICE_PLUS_TAX - AAA.TOTAL_DISCOUNT AS TOTAL_ITEM_PRICE_PER_ORDER,
TRUNC(AAA.ACE_ORD_COMPLETION_TIME) AS DATEOFDATA
FROM
( SELECT
B.ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM,
( SUM( B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT)
* B.ACE_IT_QTY ) AS SUM_PRICE_PLUS_TAX,
SUM( B.ACE_IT_DISC_AMT + B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT,
TRUNC( A.ACE_ORD_COMPLETION_TIME ) AS ACE_ORD_COMPLETION_TIME
FROM
POSDB.ACE_ORDERS A,
POSDB.ACE_ITEM_TRAN B
WHERE
A.ACE_ORD_TYPE = 'IS'
AND A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID
AND A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE
AND A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM
AND A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1)
AND A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE)
AND ( A.ACE_ORD_STATUS = 'CR'
OR A.ACE_ORD_STATUS IS NULL
OR A.ACE_ORD_STATUS LIKE ' %'
OR A.ACE_ORD_STATUS LIKE '% ')
AND ( B.ACE_IT_VOID_IND <> 'V'
OR B.ACE_IT_VOID_IND IS NULL )
GROUP BY
B.ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM,
A.ACE_ORD_COMPLETION_TIME ) AAA
ORDER BY
AAA.ACE_IT_REGION_ID,
AAA.ACE_IT_LOCATION_CODE,
AAA.ACE_IT_ORD_NUM,
AAA.ACE_ORD_COMPLETION_TIME) TAB1,
( SELECT
APD.ACE_PAYD_REGION_ID,
APD.ACE_PAYD_LOCATION_CODE,
APD.ACE_PAYD_ORD_NUM,
SUM(APD.ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT
FROM
POSDB.ACE_PAYMENT_DTL APD
WHERE
APD.ACE_PAYD_POSTING_TIMESTAMP
BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE)
AND ( APD.ACE_PAYD_STATUS <> 'V'
OR APD.ACE_PAYD_STATUS IS NULL )
GROUP BY
APD.ACE_PAYD_REGION_ID,
APD.ACE_PAYD_LOCATION_CODE,
APD.ACE_PAYD_ORD_NUM ) TAB2
WHERE
TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID
AND TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE
AND TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM
AND TAB1.TOTAL_ITEM_PRICE_PER_ORDER = TAB2.TOTAL_ACE_PAYD_AMOUNT,
AND TAB1.ACE_ORD_COMPLETION_TIME IS NOT NULL
ORDER BY
TAB1.ACE_IT_REGION_ID,
TAB1.ACE_IT_LOCATION_CODE,
TAB1.ACE_IT_ORD_NUM ) EX
To help optimize, I can suggest the following indexes as you do not have any such
displayed in your post of structures/indexes... The Payment Detail index is actually a covering index meaning is has the elements for the where, group by and the sum single field. This way it does not have to go to the raw table pages to do the query. It can all be performed directly from the indexed fields and each should be optimized for the join and where critreia.
table index on..
ACE_ORDERS ( ACE_ORD_TYPE, ACE_ORD_COMPLETION_TIME, ACE_ORD_REGION_ID, ACE_ORD_LOCATION_CODE, ACE_ORD_NUM, ACE_ORD_STATUS )
ACE_ITEM_TRAN ( ACE_IT_REGION_ID, ACE_IT_LOCATION_CODE, ACE_IT_ORD_NUM, ACE_IT_VOID_IND )
ACE_PAYMENT_DTL ( ACE_PAYD_POSTING_TIMESTAMP, ACE_PAYD_REGION_ID, ACE_PAYD_LOCATION_CODE, ACE_PAYD_ORD_NUM, ACE_PAYD_STATUS, ACE_PAYD_AMOUNT )
You need to rewrite the query using JOINS and ensure the fields being joined on have indexes.
Your revised query should be of this format:
SELECT tab1.fld1, tab.fld2
FROM tab1
JOIN tab2 ON (tab2.ID = tab1.ID AND tab2.fld3 = 'xxx')
JOIN tab3 ON (tab3.ID2 = tab2.ID2)
WHERE tab1.fld4 = 'aaa'
and tab3.fld5 > 100
This will allow the SQL optimizer to do its job.
SELECT /*+ PARALLEL(5) */
EXTER.ACE_IT_REGION_ID ,
EXTER.ACE_IT_LOCATION_CODE,
EXTER.ACE_IT_ORD_NUM,
EXTER.TOTAL_ITEM_PRICE_PER_ORDER,
EXTER.TOTAL_ACE_PAYD_AMOUNT,
EXTER.ACE_ORD_COMPLETION_TIME AS DATEOFDATA
FROM
(SELECT /*+ use_hash(TAB1,TAB2) +*/
DISTINCT
TAB1.ACE_IT_REGION_ID ,
TAB1.ACE_IT_LOCATION_CODE,
TAB1.ACE_IT_ORD_NUM,
TAB1.TOTAL_ITEM_PRICE_PER_ORDER,
TAB2.TOTAL_ACE_PAYD_AMOUNT,
TAB1.ACE_ORD_COMPLETION_TIME
FROM
(SELECT AAA.ACE_IT_REGION_ID,
AAA.ACE_IT_LOCATION_CODE,
AAA.ACE_IT_ORD_NUM,
AAA.SUM_PRICE_PLUS_TAX,
AAA.TOTAL_DISCOUNT,
-- There is no necessary that you write another subquery to finish below sql, you can do it in AAA
(AAA.SUM_PRICE_PLUS_TAX-AAA.TOTAL_DISCOUNT) AS TOTAL_ITEM_PRICE_PER_ORDER,
TRUNC(AAA.ACE_ORD_COMPLETION_TIME)
FROM (SELECT B.ACE_IT_REGION_ID AS ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE AS ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM AS ACE_IT_ORD_NUM,
(SUM(B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT)*B.ACE_IT_QTY) AS SUM_PRICE_PLUS_TAX,
SUM(B.ACE_IT_DISC_AMT+B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT,
TRUNC(A.ACE_ORD_COMPLETION_TIME ) AS ACE_ORD_COMPLETION_TIME
FROM POSDB.ACE_ORDERS A, POSDB.ACE_ITEM_TRAN B
WHERE
A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1)
AND A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE)
-- you can remove it replace by trunc(A.ACE_ORD_COMPLETION_TIME) = TRUNC(SYSDATE -1) if there is no index on this column.
-- A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1)
-- AND A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE)
AND A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID
AND A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE
AND A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM
AND A.ACE_ORD_TYPE = 'IS'
AND (A.ACE_ORD_STATUS = 'CR'
OR A.ACE_ORD_STATUS IS NULL
-- I think it better to replace blow by OR INSTR(ACE_ORD_STATUS,' ') > -1
-- OR A.ACE_ORD_STATUS LIKE ' %'
-- OR A.ACE_ORD_STATUS LIKE '% '
)
AND (B.ACE_IT_VOID_IND <> 'V' OR B.ACE_IT_VOID_IND IS NULL )
GROUP BY B.ACE_IT_REGION_ID,
B.ACE_IT_LOCATION_CODE,
B.ACE_IT_ORD_NUM,
A.ACE_ORD_COMPLETION_TIME
) AAA
-- remove order by clause in subquery, it's useless.
-- ORDER BY AAA.ACE_IT_REGION_ID,
-- AAA.ACE_IT_LOCATION_CODE,
-- AAA.ACE_IT_ORD_NUM,
-- AAA.ACE_ORD_COMPLETION_TIME
) TAB1,
(SELECT ACE_PAYD_REGION_ID,
ACE_PAYD_LOCATION_CODE,
ACE_PAYD_ORD_NUM,
SUM(ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT
FROM POSDB.ACE_PAYMENT_DTL
WHERE ACE_PAYD_POSTING_TIMESTAMP BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE)
AND (ACE_PAYD_STATUS <> 'V' OR ACE_PAYD_STATUS IS NULL )
GROUP BY
ACE_PAYD_REGION_ID,
ACE_PAYD_LOCATION_CODE,
ACE_PAYD_ORD_NUM) TAB2
WHERE TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID
AND TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE
AND TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM
-- remove order by clause in subquery, it's useless.
--ORDER BY
-- TAB1.ACE_IT_REGION_ID ,
-- TAB1.ACE_IT_LOCATION_CODE,
-- TAB1.ACE_IT_ORD_NUM
) EXTER
WHERE (EXTER.TOTAL_ITEM_PRICE_PER_ORDER = EXTER.TOTAL_ACE_PAYD_AMOUNT)
AND EXTER.ACE_ORD_COMPLETION_TIME IS NOT NULL;
-- Fix it like this for tempory, please supply explain plan for further.
-- There are so many columns like "ACE_PAYD_STATUS is not null", as you know, index could not contain null value.
-- But I think you can create an similarly index like "create index *** on ACE_PAYMENT_DTL(ACE_PAYD_STATUS,0)" to keep null values in your index.

where clause did not work with WITH

where clause did not work with WITH when i wrote where Prse ='h' it shows me an error 'Invalid column'
;with cT(FLDID ,FLD10 ,FLD610)
as
(
select * from Table556
inner join Table555 on table555.FLD9=FLD318
where FLD610=150
)
select case when fld609 <=12 then 'h' else 's' end as Prse,* from cT
where Prse ='h'
The with has nothing to do with it. You're only introducing Prse in the final SELECT clause - and you can't reference such columns from the WHERE clause (since WHERE logically runs before SELECT).
Did you want:
;with cT(Prse, FLDID ,FLD10 ,FLD610)
as
(
select case when fld609 <=12 then 'h' else 's' end as Prse, * from Table556
inner join Table555 on table555.FLD9=FLD318
where FLD610=150
)
select * from cT
where Prse ='h'
Try this one -
;WITH cte AS
(
SELECT
FLDID
, FLD10
, FLD610
, Prse =
CASE WHEN FLD609 <= 12
THEN 'h'
ELSE 's'
END
FROM dbo.Table556 t
JOIN dbo.Table555 t2 ON t2.FLD9 = t.FLD318
WHERE FLD610 = 150
)
SELECT *
FROM cte
WHERE Prse = 'h'