How to do inner join in Vertica Update? - sql

I was trying to do a inner join with 3 tables in a update query. I tried to find the solution in multiple sites but didn't get the solution.
Following a sample query I am trying:
UPDATE TGT
SET C1 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 ELSE NULL END,
C2 = CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 ELSE NULL END
FROM SRC
INNER JOIN SRC1
ON SRC.C9 = SRC1.C9
AND SRC.C9 = TGT.C9;
Thanks in Advance!!

I would expect your syntax to work. (I don't have Vertica handy but its query parser is based on Postgres.)
Perhaps -- unlike Postgres -- JOIN is not allowed in the FROM. Then you can put the join conditions in the WHERE clause:
UPDATE TGT
SET C1 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'P' THEN SRC.C1 END)
C2 = (CASE WHEN TGT.c2 = SRC.c2 AND SRC.C3 = 'D' THEN SRC.C1 END)
FROM SRC, SRC1
WHERE SRC.C9 = SRC1.C9 AND SRC.C9 = TGT.C9;

Related

SQL query case when then in where clause

I read a lot of similar questions but didn't find a solution for me. Basically I would like to have a where clause (AND PEKP.VORGANGS_ART = 'BE') only if a special condition (PFSP.EINKAUFS_KZ = 2) is true.
I tried in many ways like that:
SELECT *
FROM PFSP
LEFT OUTER JOIN PFAK on PFSP.RUECKMELDE_NR = PFAK.RUECKMELDE_NR
LEFT OUTER JOIN PEKP ON (PFSP.BESTELL_NR=PEKP.VORGANGS_NR)
AND (PFSP.BESTELL_POS_NR=PEKP.VORGANGS_POS_NR)
LEFT OUTER JOIN PMLB ON PFSP.KOMPONENTEN_ARTIKEL_NR=PMLB.ARTIKEL_NR
WHERE PFAK.KD_VORGANGS_NR = '910-001213'
AND PFSP.RUECKMELDE_STATUS = '3'
AND PFSP.BESCHAFFUNGSKENNER = 'F'
AND CASE PFSP.EINKAUFS_KZ
WHEN 2 THEN PEKP.VORGANGS_ART = 'BE'
END
but I keep getting errors:
wrong syntax near '='"
Skip the CASE, use AND/OR instead:
AND (PFSP.EINKAUFS_KZ <> 2 OR PEKP.VORGANGS_ART = 'BE')
If PFSP.EINKAUFS_KZ = 2, then PEKP.VORGANGS_ART must be equal to 'BE'.
If PFSP.EINKAUFS_KZ <> 2, it doesn't matter what PEKP.VORGANGS_ART is.
With this CASE expression:
AND 1 = CASE
WHEN PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART = 'BE' THEN 1
WHEN PFSP.EINKAUFS_KZ = 2 THEN 0
ELSE 1
END
The order of the conditions is important.
You probably want something like:
AND (
(PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART='BE')
OR PFSP.EINKAUFS_KZ <> 2 --You may need to catch NULL as well
)
SELECT *
FROM PFSP
LEFT OUTER JOIN PFAK on PFSP.RUECKMELDE_NR = PFAK.RUECKMELDE_NR
LEFT OUTER JOIN PEKP ON (PFSP.BESTELL_NR=PEKP.VORGANGS_NR)
AND (PFSP.BESTELL_POS_NR=PEKP.VORGANGS_POS_NR)
LEFT OUTER JOIN PMLB ON PFSP.KOMPONENTEN_ARTIKEL_NR=PMLB.ARTIKEL_NR
WHERE PFAK.KD_VORGANGS_NR = '910-001213'
AND PFSP.RUECKMELDE_STATUS = '3'
AND PFSP.BESCHAFFUNGSKENNER = 'F'
AND ((PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART = 'BE') OR (PFSP.EINKAUFS_KZ <> 2) )

How to tune this query in Oracle 11g

I have been asked to tune the below query and would like to know if there is any better way to tune it?
SELECT req_dtl.lab_ord_occ_test_id ,
req_dtl.order_ref_no ,
req_dtl.accession_no ,
req_dtl.test_code ,
req_dtl.test_name ,
req_dtl.test_id ,
req_dtl.schedule_id ,
req_dtl.lab_ord_occ_id ,
req_dtl.order_type ,
lab_occ.facility_id ,
lab_occ.patient_id ,
lab_occ.order_draw_dt ,
hdr.source_system ,
(SELECT CORPORATION_ACRONYM
FROM corporation c,
facility f
WHERE c.corporation_id = f.corporation_id
AND f.facility_id = lab_occ.facility_id) AS corporation_acronym,
tst.container ,
lab_occ.order_duration_type ,
occ_test.mnc_yn
FROM ORDER_REQUISITION_HEADER hdr ,
ORDER_REQUISITION_DETAIL req_dtl ,
LAB_ORDER_OCC_TEST occ_test ,
LAB_ORDER_OCC lab_occ ,
TEST tst
WHERE hdr.requisition_hdr_id = in_requisition_hdr_id
AND hdr.msg_sent_to_lab_yn = 'Y'
AND req_dtl.requisition_hdr_id = hdr.requisition_hdr_id
AND occ_test.lab_order_occ_test_id = req_dtl.lab_ord_occ_test_id
AND req_dtl.test_id = tst.test_id
AND tst.accession_type NOT LIKE 'CMP%'
AND occ_test.status != 'R'
AND occ_test.lab_order_occ_id = lab_occ.lab_order_occ_id
AND lab_occ.status = 'A'
AND occ_test.created_dt >= hdr.msg_sent_to_lab_dt
AND NVL(occ_test.test_sent_to_lab_yn,'N') = 'N'
AND NOT EXISTS
(SELECT orddata.*
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
AND orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
)
ORDER BY req_dtl.accession_no;
In the execution plan no tables are going for full table scan.Only nested loops are more.
*Suggest better way to tune this query *
AND NOT EXISTS
(SELECT orddata.*
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
AND orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
)
could be moved to FROM
FROM
...
LEFT JOIN (SELECT DISTINCT orddata.lab_order_occ_test_id
FROM MISSING_ORDER_DATA orddata,
TEST_CONFIG_HOLD_AOE tcha
WHERE orddata.test_id = tcha.test_id
AND tcha.active_yn = 'Y'
AND orddata.status_flag = 'A'
AND orddata.answer IS NULL
AND orddata.msg_sent_to_lab_yn = 'N'
) missing ON missing.lab_order_occ_test_id = occ_test.lab_order_occ_test_id
WHERE missing.lab_order_occ_test_id IS NULL
Also you should move the acronym
FROM
...
INNER JOIN (SELECT CORPORATION_ACRONYM, f.facility_id
FROM corporation c,
facility f
WHERE c.corporation_id = f.corporation_id) acr ON
acr.facility_id = lab_occ.facility_id)
...Additionally, the TEST object must have an index on accession_type otherwise the tst.accession_type not like 'CMP%' clause will be slower than necessary.
Also, the clause: NVL(occ_test.test_sent_to_lab_yn,'N') = 'N' is essentially an outer join on partially-validated data. Does the test_sent_to_lab_yn column in occ_test contain nulls? If not, consider using an IN clause along with a valid list. [it looks like a yes/no column, maybe this should be equality on 'Y' and get someone to clean up the nulls?]
Please post the explain plan so we can suggest a re-ordering of the predicates in order to minimize the row-returns in first clause....and make HINT suggestions.

Convert Oracle outer join to SQL Server

I'm having trouble converting this Oracle SQL to SQL server.
This is the query:
SELECT CM.ModuleID,
CM.ModuleDescription,
CM.ImageIndex,
CASE
WHEN CMAC.ClassID IS NULL THEN
'N'
ELSE
'Y'
END AS Checked
FROM APP_MODULES CM,
APP_PROFILE CMAP,
APP_PROFILE_CLASS CMAC
WHERE 1 = 1
AND CM.ParentModuleID IS NULL
AND CMAP.ProfileID(+) = CMAC.ProfileID
AND CM.ModuleID = CMAC.ModuleID(+)
AND CMAC.ProfileID(+) = P_ProfileID
AND CM.Activated = 'Y'
ORDER BY CM.Ordem;
Can anyone help me?
This should work in SQL Server:
SELECT CM.ModuleID,
CM.ModuleDescription,
CM.ImageIndex,
CASE
WHEN CMAC.ClassID IS NULL THEN
'N'
ELSE
'Y'
END AS Checked
FROM APP_MODULES CM,
LEFT JOIN APP_PROFILE_CLASS CMAC
ON(CMAC.ProfileID = P_ProfileID AND CM.ModuleID = CMAC.ModuleID)
LEFT JOIN APP_PROFILE CMAP
ON(CMAP.ProfileID = CMAC.ProfileID)
WHERE 1 = 1
AND CM.ParentModuleID IS NULL
AND CM.Activated = 'Y'
ORDER BY CM.Ordem;

Oracle SubQuery (Display subquery columns)

I cannot seem to find via searching how I would be able to return some of the columns from the the below sub queries. Specifically B.TAP_STAT_HSL/C.TAP_STAT_HSL. I'm not sure if I should be joining instead, but any help would be greatly appreciated.
SELECT
A.HSE_KEY_HSE AS HOUSEKEY,
A.DROP_STAT_HSE AS DROPSTATUS
A.TAP_STAT_HSL AS ITAPSTAT
FROM OPS$SEA.HSE_BASE,OPS$SEA.HSL_LOB,OPS$SEA.OOR_ORDER_OPEN A
WHERE A.HSE_KEY_HSE = A.HSE_KEY_HSL
AND A.HSE_KEY_HSL = A.HSE_KEY_OOR
AND A.DROP_STAT_HSE = '1'
AND A.LOB_IND_HSL = 'I'
AND A.TAP_STAT_HSL IN ('0','2')
AND A.ORD_STAT_OOR <> 'O'
AND EXISTS (SELECT 1
FROM OPS$SEA.HSE_BASE B,OPS$SEA.HSL_LOB B, OPS$SEA.OOR_ORDER_OPEN B
WHERE A.HSE_KEY_HSE = B.HSE_KEY_HSE
AND B.HSE_KEY_HSE = B.HSE_KEY_HSL
AND B.HSE_KEY_HSL = B.HSE_KEY_OOR
AND B.DROP_STAT_HSE = '1'
AND B.LOB_IND_HSL = 'C'
AND B.TAP_STAT_HSL IN ('0','2')
AND B.ORD_STAT_OOR <> 'O')
AND EXISTS (
SELECT 1
FROM OPS$SEA.HSE_BASE C,OPS$SEA.HSL_LOB C, OPS$SEA.OOR_ORDER_OPEN C
WHERE A.HSE_KEY_HSE = C.HSE_KEY_HSE
AND C.HSE_KEY_HSE = C.HSE_KEY_HSL
AND C.HSE_KEY_HSL = C.HSE_KEY_OOR
AND C.DROP_STAT_HSE = '1'
AND C.LOB_IND_HSL = 'T'
AND C.TAP_STAT_HSL IN ('0','2')
AND C.ORD_STAT_OOR <> 'O')}
Hmmm....
I believe your query can be re-written as follows:
WITH Allowed_Rows (houseKey, dropStatus, ipApStat, indicator)
as (SELECT a.HSE_KEY_HSE, a.DROP_STAT_HSE,
b.TAP_STAT_HSL, b.LOB_IND_HSL
FROM OPS$SEA.HSE_BASE as a
JOIN OPS$SEA.HSL_LOB as b
ON b.HSE_KEY_HSL = a.HSE_KEY_HSE
AND b.LOB_IND_HSL IN ('I', 'C', 'T')
AND b.TAB_STAT_HSL IN ('0', '2')
JOIN OPS$SEA.OOR_Order_Open as c
ON c.HSE_KEY_OOR = a.HSE_KEY_HSE
AND c.ORD_STAT_OOR <> '0'
WHERE a.DROP_STAT_HSE = '1')
SELECT houseKey, dropStatus, ipApStat
FROM Allowed_Rows as a
WHERE a.indicator = 'I'
AND EXISTS (SELECT '1'
FROM Allowed_Rows as b
WHERE b.houseKey = a.houseKey
AND b.indicator = 'C')
AND EXISTS (SELECT '1'
FROM Allowed_Rows as b
WHERE b.houseKey = a.houseKey
AND b.indicator = 'T')
You didn't properly qualify some of your tables, and used the same alias for multiple tables (which I'm surprised didn't generate a syntax error), so I had to make my best guess as to where things actually belong. There are a couple of other variations possible, depending on the other (unlisted) requirements and constraints.
And why and how do you need to return the 'other' values of TAP_STAT_HSL? DO you need all possible combinations? The value of the row for B or C instead of A? What?

Stored procedure: how can I set a field value in the returned data without changing the tables it came from?

SELECT
EQ.EventQuestId,
EQ.QuestionText,
EQ.HelpText,
EQ.EventQuestOptType,
EQ.DisplayOrder AS QuestDisplayOrder,
EQO.EventQuestOptId,
EQO.OptionText,
EQO.IsOtherSpecify,
STJC.STJCategory,
EQO.DisplayOrder AS OptDisplayOrder,
EA.EventId, EA.AnswerText
FROM EventQuest EQ
INNER JOIN EventQuestOpt EQO
ON EQ.EventQuestId = EQO.EventQuestId
LEFT JOIN EventAnswer EA
ON EA.EventQuestId = EQ.EventQuestId
AND EA.EventQuestOptId = EQO.EventQuestOptId
AND EventId = #EventId
LEFT JOIN dbo.STJCategories STJC
ON STJC.STJID = EQO.STJID
WHERE EQO.Status <> 'false'
ORDER BY EQ.DisplayOrder, EQO.DisplayOrder
I have this in my stored proc. I want to set the EQ.QuestionText to the STJC.STJCategory value wherever EQ.QuestionText = "example". I just want this in the returned result, not in table it came from. How do I go about this as I've never tried to do this before and have no clue where to begin with that, if it's possible.
I hope this makes sense.
You can use case for that:
select case
when EQ.QuestionText = 'example' then STJC.STJCategory
else EQ.QuestionText
end as QuestionText
use a CASE statement
SELECT
EQ.EventQuestId,
CASE EQ.QuestionText WHEN 'example'
THEN STJC.STJCategory ELSE EQ.QuestionText END QuestionText ,
EQ.HelpText,
EQ.EventQuestOptType,
EQ.DisplayOrder AS QuestDisplayOrder,
EQO.EventQuestOptId,
EQO.OptionText,
EQO.IsOtherSpecify,
STJC.STJCategory,
EQO.DisplayOrder AS OptDisplayOrder,
EA.EventId, EA.AnswerText
FROM EventQuest EQ
INNER JOIN EventQuestOpt EQO
ON EQ.EventQuestId = EQO.EventQuestId
LEFT JOIN EventAnswer EA
ON EA.EventQuestId = EQ.EventQuestId
AND EA.EventQuestOptId = EQO.EventQuestOptId
AND EventId = #EventId
LEFT JOIN dbo.STJCategories STJC
ON STJC.STJID = EQO.STJID
WHERE EQO.Status <> 'false'
ORDER BY EQ.DisplayOrder, EQO.DisplayOrder