I need to pick the dynamic column based on some condition and it has to be used in where condition.
AuditLog::select('audit_log.id')
->join('columns_list', 'columns_list.id', '=', 'audit_log.interim_column_table_id')
->join('transactions', 'transactions.id', '=', 'audit_log.interim_transaction_id')
->whereRaw(columns_list.column_name = ?', ["p_gross"])
->latest('audit_log_transaction_level.created_at')
In the above query, I need to replace the ["p_gross"] with the following code
CASE
WHEN transactions.transaction_type_id = 1 THEN 'p_gross'
WHEN transactions.transaction_type_id = 2 THEN 's_gross'
END
here is the raw SQL for a better understanding
select audit_log.id
from audit_log
join columns_list on columns_list.id = audit_log.interim_column_table_id
join transactions on audit_log.interim_transaction_id = transactions.id
where
columns_list.column_name = CASE
WHEN transactions.tbi_transaction_type_id = 1 THEN 'p_gross'
WHEN transactions.tbi_transaction_type_id = 2 THEN 's_gross'
END
order by audit_log.created_at desc
Related
I'm trying to add a conditional SELECT column in a query and I'm having trouble writing it out:
SELECT v.GLTypeID,
v.something,
v.somethignElse,
CASE WHEN (SELECT TOP 1 Value FROM InterfaceParam WHERE InterfaceId = 0 AND Descr = 'gf') = 1 THEN a.CreditID ELSE NULL END AS CreditMemoID
FROM vGLDetails2 v
....
LEFT OUTER JOIN AssociationFund f
ON v.FundID = f.FundID
LEFT JOIN dbo.APLedger a ON v.RelID = a.APLedgerID AND v.RelTypeID IN (39, 40)
....
ORDER BY v.Code;
The query above works, however if the CASE statement is still returning an additional column regardless of the result of the subquery. How can I remove it if the subquery doesn't return a row?
How can I do this?
Change the location of AS. For example:
SELECT v.GLTypeID,
v.something,
v.somethignElse,
CASE WHEN (
SELECT TOP 1 Value
FROM InterfaceParam
WHERE InterfaceId = 0 AND Descr = 'creditMemo') = 1
THEN a.CreditID -- AS is not valid here
END AS CreditMemoID -- AS is valid here
FROM vGLDetails2 v
....
LEFT OUTER JOIN AssociationFund f
ON v.FundID = f.FundID
LEFT JOIN dbo.APLedger a ON v.RelID = a.APLedgerID AND v.RelTypeID IN (39, 40)
....
ORDER BY v.Code;
Note: I removed ELSE NULL since this is the default behavior of CASE.
I'm trying to return a single row based on this where statement
WHERE
(C.id = G.community_id
AND P.service_type_id = G.service_type_id
AND I.unit_class_id = G.unit_class_id)
OR
(C.id = G.community_id
AND P.service_type_id = G.service_type_id)
The issue is I have to get a row based on multiple criteria and the more that match determines the final match. The statement above returns a row just fine if it matches the bottom or statement, but if it matches the first OR it returns results for both statements.
LIMIT 1 doesn't work either as sometimes it gives preference to the wrong result.
EDIT:
community_id
service_type_id
unit_class_id
1
1
1
1
1
null
Because of the way the table is both rows are true, my understanding was SQL took the first one that was true and returned it.
I apologize for not a lot of info I was hoping maybe there was just a bit of info I was missing. Here is my query.
CREATE VIEW view_invoice_line_item_gl_code
AS
SELECT
DISTINCT(ILI.invoice_line_item_id) AS invoice_line_item_id,
C.community_id AS community_id,
S.service_type_id AS service_type_id,
U.unit_class_id AS unit_class_id,
LIP.line_item_provider_id AS line_item_provider_id,
(SELECT gl_code_id
FROM gl_code G
WHERE (C.community_id = G.community_id
AND P.service_type_id = G.service_type_id)
AND ((G.unit_class_id IS NULL
AND G.line_item_provider_id IS NULL)
OR
(I.unit_class_id = G.unit_class_id
AND G.line_item_provider_id IS NULL)
OR
(I.unit_class_id = G.unit_class_id
AND ILI.line_item_provider_id = G.line_item_provider_id)
)) AS gl_code_id
FROM
invoice I
JOIN
invoice_line_item ILI ON (ILI.invoice_id = I.invoice_id)
JOIN
invoice_header IH ON (I.invoice_header_id = IH.invoice_header_id)
JOIN
provider_community_account PC ON (I.provider_community_account_id = PC.provider_community_account_id)
JOIN
line_item_provider LIP ON (ILI.line_item_provider_id = LIP.line_item_provider_id)
JOIN
unit_class U ON (I.unit_class_id = U.unit_class_id)
JOIN
community C ON (PC.community_id = C.community_id)
JOIN
provider P ON (PC.provider_id = P.provider_id)
JOIN
service_type S ON (P.service_type_id = S.service_type_id)
I'm assuming that you want to get the record that matches the most conditions first. One way to do that is to order by the number of matching conditions (in this case only one condition is different):
SELECT TOP 1 ...
FROM ...
WHERE
C.id = G.community_id
AND P.service_type_id = G.service_type_id
ORDER BY CASE WHEN I.unit_class_id = G.unit_class_id THEN 1 ELSE 0 END DESC
The first condition implies the second, so you can simplify it like this:
WHERE
C.id = G.community_id
AND P.service_type_id = G.service_type_id
You say where (A AND B) OR A so where A is sufficient.
You'll need to compute a "score" somehow. If you consider each predicate awards 1 point, then you could do something like:
select *
from (
select *,
case when <predicate1> then 1 else 0 end +
case when <predicate2> then 1 else 0 end as score
from t
WHERE
(C.id = G.community_id
AND P.service_type_id = G.service_type_id
AND I.unit_class_id = G.unit_class_id
)
OR
(
C.id = G.community_id
AND P.service_type_id = G.service_type_id
)
)
ORDER BY score DESC
LIMIT 1
I am looking to roll up my numbers.
SELECT
SORDERQ.SOHNUM_0,
YQTYORD_0,
ORDINVNOT_0
FROM LIVE.SORDER
LEFT JOIN LIVE. SORDERQ ON SORDER.SOHNUM_0 = SORDERQ.SOHNUM_0
WHERE SORDER.SOHNUM_0 = 'SC111-162420_19'
AND ZBPSELECTION_0 <> ''
AND YCROPYR_0 = '2019'
AND SORDER.SALFCY_0 = '111'
I want to return 1 record per SOHNUM_0,the sum of YQTYORD_0 by SOHNUM_0 and ORDINVNOT_0.
I want to return 1 record per SOHNUM_0,the sum of YQTYORD_0 by SOHNUM_0 and ORDINVNOT_0.
Are you just looking for simple aggregation?
SELECT
q.SOHNUM_0,
SUM(YQTYORD_0) SUM_YQTYORD_0,
ORDINVNOT_0
FROM LIVE.SORDER o
LEFT JOIN LIVE.SORDERQ q ON o.SOHNUM_0 = q.SOHNUM_0
WHERE
o.SOHNUM_0 = 'SC111-162420_19'
AND o.SALFCY_0 = '111'
AND ZBPSELECTION_0 <> ''
AND YCROPYR_0 = '2019'
GROUP BY
q.SOHNUM_0,
ORDINVNOT_0
Note:
I modified your query so it uses table aliases - this makes it shorter
you should prefix all columns in the query with the table they belong to, to make your query unmabiguous and easier to understand
sorry if this is a dumb question, I'm new to PL/SQL.
I have a PL/SQL Stored Procedure which retrieves data from a table.
There are 2 optional parameters which can be null. If they're not null they should be part of the WHERE clause.
This is the SELECT:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND PN.PART_TYPE_ID = IN_PART_TYPE_ID
AND PN.PART_GROUP_ID = IN_PART_GROUP_ID
ORDER BY PN.PART_NUMBER;
The two variables are IN_PART_TYPE_ID and IN_PART_GROUP_ID. Is there any way to evaluate the WHERE clauses regarding these two variables only when they're NOT NULL? Or the only way is to repeat the SELECT 3 times using IF clauses and changing the WHERE clauses?
OR operatior will help:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND (PN.PART_TYPE_ID = IN_PART_TYPE_ID or IN_PART_TYPE_ID is null)
AND (PN.PART_GROUP_ID = IN_PART_GROUP_ID or IN_PART_GROUP_ID is null)
ORDER BY PN.PART_NUMBER;
Another option is to use NVL:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND PN.PART_TYPE_ID = NVL(IN_PART_TYPE_ID, PN.PART_TYPE_ID)
AND PN.PART_GROUP_ID = NVL(IN_PART_GROUP_ID, PN.PART_GROUP_ID)
ORDER BY PN.PART_NUMBER;
But it will work only if PN.PART_TYPE_ID and PN.PART_GROUP_ID is not null
I have the following query which gives gives req_no and order_no. order_no is a from a sub_query which you can see from below sql. For a few req_no there are more than one order_no's and because of that I get ORA-01427: single-row subquery returns more than one row.
I would like to display both the order_no for one req_no, how can I achieve this?
Any help is highly appreciable.
Thanks
P.S. Our client's one database is still Oracle 8i.
SELECT max_qst.req_no,
(SELECT DISTINCT max_odr.order_no
FROM maximo_orders max_odr,
maximo_order_revisions max_odv,
maximo_order_items max_odi,
maximo_order_dates max_odd,
maximo_requisition_order max_rqo,
maximo_requisition_details max_req
WHERE max_req.req_no = max_qst.req_no
AND max_req.req_yr = max_qst.req_yr
AND max_odr.order_no = max_odi.order_no
AND max_odi.order_item_id = max_odd.order_item_id
AND max_req.requisition_item_id = max_rqo.requisition_item_id
AND max_rqo.order_schedule_id = max_odd.order_schedule_id
AND max_odv.order_no = max_odi.order_no
AND max_odv.revision_no =
(SELECT MAX (max_alias.revision_no)
FROM maximo_order_revisions max_alias
WHERE max_alias.order_no = max_odv.order_no)
AND maximo_order_item (max_odi.order_no,
max_odv.revision_no,
max_odi.order_item_id
) = 'CONFIRMED'
)
FROM maximo_requisitions max_qst, maximo_requisition_details max_qsd
WHERE max_qst.qst_id = max_qsd.qst_id
AND max_qst.enter_date = '2001'
AND max_qst.req_no = 'PUR_12WX'
Update 1
Desired out put.
REQ_No ORDER_NO
PUR_12WX PR_9078
PUR_12WX PR_9079
Use a join instead of a correlated sub-query.
I've removed the max_qst references from the sub-query and moved them to the join predicate.
I've also just changed it to use a LEFT JOIN. This allows for the possibility of there being no order_no values returned.
SELECT
max_qst.req_no,
sub_query.order_no
FROM
maximo_requisitions max_qst
INNER JOIN
maximo_requisition_details max_qsd
ON max_qst.qst_id = max_qsd.qst_id
LEFT JOIN
(
SELECT DISTINCT
max_odr.order_no,
max_req.req_no,
max_req.req_yr
FROM
maximo_orders max_odr,
maximo_order_revisions max_odv,
maximo_order_items max_odi,
maximo_order_dates max_odd,
maximo_requisition_order max_rqo,
maximo_requisition_details max_req
WHERE
max_odr.order_no = max_odi.order_no
AND max_odi.order_item_id = max_odd.order_item_id
AND max_req.requisition_item_id = max_rqo.requisition_item_id
AND max_rqo.order_schedule_id = max_odd.order_schedule_id
AND max_odv.order_no = max_odi.order_no
AND max_odv.revision_no = (SELECT MAX (max_alias.revision_no)
FROM maximo_order_revisions max_alias
WHERE max_alias.order_no = max_odv.order_no)
AND maximo_order_item (max_odi.order_no, max_odv.revision_no, max_odi.order_item_id) = 'CONFIRMED'
)
suq_query
ON max_qst.req_no = sub_query.req_no
AND max_qst.req_yr = sub_query.req_yr
WHERE
max_qst.enter_date = '2001'
max_qst.req_no = 'PUR_12WX'
You can use
DISTINCT
or
WHERE ROWNUM = 1
But I'd suggest you investigate why you're getting more than one row returned: Have you misunderstood the data, have you missed a join, is there erroneous or duplicate data etc etc.