Use if in where statement - sql

I have 4 table:
Table_op_type
Table_maintenancetype
Table_repair_time
Table_repair_type
Each table has one column that can true or false and I have one Table_maintenancereport that has many columns and 4 columns in Table_maintenancereport foreign key given from 4 up table when I select Table_maintenancereport and one row in each table is true code working fine but when more than one row returned from table give this error.
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
How can I fix it?
My code is:
SELECT *
FROM Table_maintenancereport
WHERE mtypeid IN (IIF(#smtype = 1, (SELECT Table_maintenancetype.id FROM Table_maintenancetype WHERE enable_search = 1), mtypeid))
AND op_typeid IN (IIF(#sop IN (1), (SELECT Table_op_type.id FROM Table_op_type WHERE enable_search = 1), op_typeid))
AND repaire_timeid IN (IIF(#stime IN (1), (SELECT Table_repair_time.id FROM Table_repair_time WHERE enable_search = 1), repaire_timeid))
AND repaire_typeid IN (IIF(#stype = 1, (SELECT Table_repair_type.id FROM Table_repair_type WHERE enable_search = 1), repaire_typeid));

You need to fix the where conditions. You can do this with basic logic operators. Sets cannot be returned by iif() or by case() expressions.
So:
WHERE (#smtype <> 1 OR
mtypeid IN (SELECT Table_maintenancetype.id FROM Table_maintenancetype WHERE enable_search = 1)
) AND
(#sop <> 1 OR
op_typeid IN (SELECT Table_op_type.id FROM Table_op_type WHERE enable_search = 1)
) AND
(#stime <> 1 OR
repaire_timeid IN (SELECT Table_repair_time.id FROM Table_repair_time WHERE enable_search = 1)
) AND
(#stype <> 1 OR
repaire_typeid IN (SELECT Table_repair_type.id FROM Table_repair_type WHERE enable_search = 1)
);

If I am interpreting what you are trying to do correctly:
SELECT *
FROM Table_maintenancereport mr
LEFT OUTER JOIN Table_maintenancetype mt ON mr.mtypeid = mt.id AND enable_search = 1
LEFT OUTER JOIN Table_op_type ot ON mr.op_typeid = ot.id AND enable_search = 1
LEFT OUTER JOIN Table_repair_time rt ON mr.repaire_timeid = rt.id AND enable_search = 1
LEFT OUTER JOIN Table_repair_type rty ON mr.repaire_typeid = rty.id AND enable_search = 1
WHERE (ISNULL(#smtype,-1) != 1 OR mt.id IS NOT NULL)
AND (ISNULL(#sop,-1) != 1 OR ot.id IS NOT NULL)
AND (ISNULL(#stime,-1) != 1 OR rt.id IS NOT NULL)
AND (ISNULL(#stype,-1) != 1 OR rty.id IS NOT NULL)
so for each #variable, if it is set to 1, the corresponding field has to be one of the search enabled ids to appear in the output. If a variable is not set to 1, then it will not filter the corresponding field.

Maybe you can use CASE WHEN statement in where clause like:
select
*
from
Table_maintenancereport
where
case
when #smtype = 1 then mtypeid in (
select Table_maintenancetype.id
from
Table_maintenancetype
where
enable_search = 1)
else mtypeid = mtypeid end
....

Related

Conditionally adding a column in a SQL query

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.

Join On conditional column SQL

I'm trying to do a LEFT join on a created column(y_prcs_new) in SQL but I get the next error:
"Column 'y_prcs_new' cannot be resolved"
This is the query:
SELECT
sh.i_rqst,
sh.y_rqst,
sh.c_close_reason,
CASE WHEN sh.y_prcs IS NULL THEN 3
WHEN sh.y_prcs = 1 AND sh.c_close_reason = 5 THEN 3
WHEN (sh.y_prcs IS NOT NULL OR sh.y_prcs != 1) AND sh.c_close_reason != 5 THEN sh.y_prcs
END AS y_prcs_new,
fr.t_close_reason
FROM st_hist sh
LEFT JOIN
(SELECT DISTINCT fr.c_close_reason, fr.t_close_reason, fr.y_prcs
FROM sRsn fr) AS fr
ON sh.c_close_reason = fr.c_close_reason
AND y_prcs_new = fr.y_prcs
Do you know how can fix it?
You query is incorrect as join statement executes first and then select statement in the end of the query, so on join query could not find y_prcs_new.
select
i_rqst,
y_rqst,
c_close_reason,
y_prcs_new,
t_close_reason
from
(
SELECT
i_rqst,
y_rqst,
c_close_reason,
CASE WHEN y_prcs IS NULL THEN 3
WHEN y_prcs = 1 AND c_close_reason = 5 THEN 3
WHEN (y_prcs IS NOT NULL OR y_prcs != 1) AND c_close_reason != 5 THEN y_prcs
END AS y_prcs_new
FROM st_hist
) sh
LEFT JOIN
( SELECT
DISTINCT c_close_reason,
t_close_reason,
y_prcs
FROM sRsn
) fr
ON sh.c_close_reason = fr.c_close_reason
AND sh.y_prcs_new = fr.y_prcs

Pl sql get x character of a string in a query

SELECT MR.MUSTERI_ROL_AD AS ACENTE_AD , ////HERE\\\\
(SELECT mrrt.musteri_rol_ad
FROM calisan ct, musteri_rol mrrt, musteri mmt
where ct.bagli_rol_id = a.acente_id
AND ct.calisan_rol_id = mrrt.musteri_rol_id
AND mrrt.musteri_id = mmt.musteri_id
AND ct.teknik_personel='H'
AND ct.calisan_rol_id is not null
and rownum < 2)Bayi_Yetkili_Kisi,
( case when M.TCK_NO is null then M.VKN_NO
else null end)VKN_NO,
(Select (SELECT taa.adresi
FROM tobb_acente ta, tobb_acente_adres taa
WHERE ta.levhano = a.levha_no
AND ta.tobb_acente_sorgu_id = taa.tobb_acente_sorgu_id
AND rownum < 2)
FROM musteri_adres mat, musteri_rol mrt, musteri mt, adres ad
WHERE mrt.musteri_rol_id = a.acente_id
AND mt.musteri_id = mrt.musteri_id
AND mat.musteri_id(+) = mt.musteri_id
AND ad.adres_id(+) = mat.adres_id AND rownum < 2) adress,
(SELECT mi.aciklama
FROM musteri_iletisim mi, musteri_rol_iletisim mri
where mi.musteri_id = m.musteri_id
AND mi.iletisim_tip_kod =
pck_const_iletisim_tip.cep_telefon()
AND mri.musteri_rol_id = mr.musteri_rol_id
and mi.musteri_iletisim_id = mri.musteri_iletisim_id
and rownum < 2) as CEpTELEFON ////// HERE \\\\\
FROM MUSTERI_ROL MR, MUSTERI M, ACENTE A,SATIS_KANALI SK
WHERE MR.MUSTERI_ID = M.MUSTERI_ID
AND MR.MUSTERI_ROL_ID = A.ACENTE_ID
AND A.SATIS_KANALI_ID = SK.SATIS_KANALI_ID
AND MR.ROL_ID = 1
AND A.Uretim_Kaynagi = 'E'
AND A.UST_ACENTE_ID is null
AND MR.Ust_Musteri_Rol_Id is null
AND M.VKN_NO != 'x'
AND TO_CHAR(TRUNC(MR.Bitis_Tarih), 'DD/MM/YYYY') is null or MR.Bitis_Tarih = SYSDATE
Hi guys i need some help about split in Oracle's SQL i get ACENTE_AD x character and i wanna see only first 5 character. and i get CEpTELEFON like 012345678 and i wanna split first 3 character(012) in a column and last 6 character(345678) the in other column. thanks.
You can use substr() string manipulation function to split your phone value in the outer select statement by considering your original query as a subquery.
SELECT t.Bayi_Yetkili_Kisi, t.Vkn_No, t.Adres,
substr(CepTelefonu,1,3) as AlanKodu, substr(CepTelefonu,-6) as CepTelefonu
FROM
(
SELECT MR.MUSTERI_ROL_AD AS ACENTE_AD,
(SELECT mrrt.musteri_rol_ad
FROM musteri_rol mrrt
JOIN calisan ct ON ct.calisan_rol_id = mrrt.musteri_rol_id
JOIN musteri mmt ON mmt.musteri_id = mrrt.musteri_id
WHERE ct.bagli_rol_id = a.acente_id
AND ct.teknik_personel = 'H'
AND ct.calisan_rol_id is not null
AND rownum < 2) as Bayi_Yetkili_Kisi,
(CASE
WHEN M.TCK_NO is null THEN
M.VKN_NO
ELSE
null
END) as Vkn_No,
(SELECT (SELECT taa.adresi
FROM tobb_acente ta
JOIN tobb_acente_adres taa
ON taa.tobb_acente_sorgu_id = ta.tobb_acente_sorgu_id
WHERE ta.levhano = a.levha_no
AND rownum < 2)
FROM musteri mt
JOIN musteri_rol mrt ON mrt.musteri_id = mt.musteri_id
LEFT JOIN musteri_adres mat ON mat.musteri_id = mt.musteri_id
LEFT JOIN adres ad ON ad.adres_id = mat.adres_id
WHERE mrt.musteri_rol_id = a.acente_id
AND rownum < 2) as Adres,
(SELECT mi.aciklama
FROM musteri_iletisim mi
JOIN musteri_rol_iletisim mri ON mri.musteri_iletisim_id = mi.musteri_iletisim_id
WHERE mi.musteri_id = m.musteri_id
AND mi.iletisim_tip_kod = pck_const_iletisim_tip.cep_telefon() -- I think the right hand side implies a stored function, doesn't it?
AND mri.musteri_rol_id = mr.musteri_rol_id
AND rownum < 2) as CepTelefonu
FROM MUSTERI_ROL MR
JOIN MUSTERI M ON M.MUSTERI_ID = MR.MUSTERI_ID
JOIN ACENTE A ON A.ACENTE_ID = MR.MUSTERI_ROL_ID
JOIN SATIS_KANALI SK ON SK.SATIS_KANALI_ID = A.SATIS_KANALI_ID
WHERE MR.ROL_ID = 1
AND A.Uretim_Kaynagi = 'E'
AND A.UST_ACENTE_ID is null
AND MR.Ust_Musteri_Rol_Id is null
AND M.VKN_NO != 'x'
AND to_char(trunc(MR.Bitis_Tarih), 'dd/mm/yyyy') is null
OR MR.Bitis_Tarih = sysdate
) t;
Btw, Consider using ANSI-92 style SQL rather than former ANSI-89 with comma-seperated tables written like the above one. It's easier to write, understand and maintain.

SQL subquery filter using parent table fields

I have a query as below:
SELECT tr.AccountFK ,
TransactionRequestStatus = CASE
WHEN tr.TransactionRequestStatusFK = 2 THEN 'Accepted'
ELSE 'Rejected'
END,
tr.TransactionRequestID
FROM [CRM].[acc].[TransactionRequest] as tr
INNER JOIN CRM.acc.TransactionRequestHistory as trh
ON tr.TransactionRequestID = trh.TransactionRequestFK
where tr.TransactionRequestTypeFK = 3 --bill split
and TransactionRequestStatusFK in (2, 3) --Approved, Rejected
--Filter- on each item
and (tr.TransactionRequestStatusFK = 2 and tr.TransactionRequestID not in (select tr.TransactionRequestID from crm.acc.TransactionRequest tr
INNER JOIN CRM.acc.TransactionRequestHistory as trh
ON tr.TransactionRequestID = trh.TransactionRequestFK
where tr.TransactionRequestID = trh.TransactionRequestFK
and trh.EventFK = 15)
or
tr.TransactionRequestStatusFK = 3 and tr.Notes not like '%No Action%')
group by tr.AccountFK, tr.TransactionRequestStatusFK, tr.TransactionRequestID
I have a subquery in the where clause to apply a filter on each item but this subquery join is the same has the join in the main query, is there any way to re-use the main query table and avoid repeating same code in the subquery.
Using CTE. Assuming the column names in both crm.acc.TransactionRequest and CRM.acc.TransactionRequestHistory are distinct, the following should work. If they aren't, then you'll have to specify the columns with their alias in the Select of cte.
with cte as
(select * from crm.acc.TransactionRequest tr
INNER JOIN CRM.acc.TransactionRequestHistory as trh
ON tr.TransactionRequestID = trh.TransactionRequestFK)
SELECT AccountFK ,
TransactionRequestStatus = CASE
WHEN TransactionRequestStatusFK = 2 THEN 'Accepted'
ELSE 'Rejected'
END,
TransactionRequestID
FROM cte
where TransactionRequestTypeFK = 3 --bill split
and TransactionRequestStatusFK in (2, 3) --Approved, Rejected
--Filter- on each item
and (TransactionRequestStatusFK = 2 and TransactionRequestID not in
(select TransactionRequestID from cte
where TransactionRequestID = TransactionRequestFK
and EventFK = 15)
or
TransactionRequestStatusFK = 3 and Notes not like '%No Action%')
group by AccountFK, TransactionRequestStatusFK, TransactionRequestID

TOP Returning null

I have the following view below. The second nested select is always returning null when I use the TOP(1) clause, but when I remove this clause it returns the data as expected, just more rows than is needed. Does anyone see anything that would explain this?
SELECT TOP (100) PERCENT
a.ITEMID AS Model
,id.CONFIGID
,id.INVENTSITEID AS SiteId
,id.INVENTSERIALID AS Serial
,it.ITEMNAME AS Description
,CASE WHEN it.DIMGROUPID LIKE '%LR-Y' THEN 'Y'
ELSE 'N'
END AS SerialNumberReqd
,ISNULL(it.PRIMARYVENDORID, N'') AS Vendor
,ISNULL(vt.NAME, N'') AS VendorName
,id.INVENTLOCATIONID AS Warehouse
,id.WMSLOCATIONID AS Bin
,ISNULL(CONVERT(varchar(12), CASE WHEN C.DatePhysical < '1901-01-01'
THEN NULL
ELSE C.DatePhysical
END, 101), N' ') AS DeliveryDate
,CASE WHEN (a.RESERVPHYSICAL > 0
OR C.StatusIssue = 1)
AND c.TransType = 0 THEN C.PONumber
ELSE ''
END AS SoNumber
,'' AS SoDetail
,ISNULL(C.PONumber, N'') AS RefNumber
,ISNULL(CONVERT(varchar(12), CASE WHEN ins.ProdDate < '1901-01-01'
THEN NULL
ELSE ins.PRODDATE
END, 101), N' ') AS DateReceived
,it.STKSTORISGROUPID AS ProdGroup
,ISNULL(CONVERT(varchar(12), CASE WHEN ins.ProdDate < '1901-01-01'
THEN NULL
ELSE ins.PRODDATE
END, 101), N' ') AS ProductionDate
,it.ITEMGROUPID
,it.STKSTORISGROUPID AS MerchandisingGroup
,CASE WHEN a.postedValue = 0
THEN (CASE WHEN D.CostAmtPosted = 0 THEN D.CostAmtPhysical
ELSE D.CostAmtPosted
END)
ELSE a.POSTEDVALUE
END AS Cost
,CASE WHEN a.PHYSICALINVENT = 0 THEN a.Picked
ELSE a.PhysicalInvent
END AS PhysicalOnHand
,ins.STKRUGSQFT AS RugSqFt
,ins.STKRUGVENDSERIAL AS RugVendSerial
,ins.STKRUGVENDDESIGN AS RugVendDesign
,ins.STKRUGEXACTSIZE AS RugExactSize
,ins.STKRUGCOUNTRYOFORIGIN AS RugCountryOfOrigin
,ins.STKRUGQUALITYID AS RugQualityId
,ins.STKRUGCOLORID AS RugColorId
,ins.STKRUGDESIGNID AS RugDesignId
,ins.STKRUGSHAPEID AS RugShapeId
,CASE WHEN (a.AVAILPHYSICAL > 0) THEN 'Available'
WHEN (id.WMSLOCATIONID = 'NIL') THEN 'Nil'
WHEN (a.RESERVPHYSICAL > 0)
AND (c.TransType = 0) THEN 'Committed'
WHEN (a.RESERVPHYSICAL > 0) THEN 'Reserved'
WHEN (id.WMSLOCATIONID LIKE '%-Q') THEN 'Damaged'
WHEN (a.Picked > 0) THEN 'Picked'
ELSE 'UNKNOWN'
END AS Status
,'' AS ReasonCode
,'' AS BaseModel
,ISNULL(CAST(ins.STKSTORISCONFIGINFO AS nvarchar(1000)), N'') AS StorisConfigInfo
,ISNULL(C.ConfigSummary, N'') AS ConfigSummary
FROM
dbo.INVENTSUM AS a WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS id WITH (NOLOCK)
ON id.DATAAREAID = a.DATAAREAID
AND id.INVENTDIMID = a.INVENTDIMID
LEFT OUTER JOIN dbo.INVENTTABLE AS it WITH (NOLOCK)
ON it.DATAAREAID = a.DATAAREAID
AND it.ITEMID = a.ITEMID
LEFT OUTER JOIN dbo.VENDTABLE AS vt WITH (NOLOCK)
ON vt.DATAAREAID = it.DATAAREAID
AND vt.ACCOUNTNUM = it.PRIMARYVENDORID
LEFT OUTER JOIN dbo.INVENTSERIAL AS ins WITH (NOLOCK)
ON ins.DATAAREAID = id.DATAAREAID
AND ins.INVENTSERIALID = id.INVENTSERIALID
LEFT OUTER JOIN (SELECT TOP (1)
itt.ITEMID
,invt.INVENTSERIALID
,itt.DATEPHYSICAL AS DatePhysical
,itt.TRANSREFID AS PONumber
,itt.TRANSTYPE AS TransType
,itt.STATUSISSUE AS StatusIssue
,dbo.stkRowsToColumn(itt.INVENTTRANSID, 'STI') AS ConfigSummary
,itt.RECID
FROM
dbo.INVENTTRANS AS itt WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS invt WITH (NOLOCK)
ON invt.DATAAREAID = itt.DATAAREAID
AND invt.INVENTDIMID = itt.INVENTDIMID
WHERE
(itt.DATAAREAID = 'STI')
AND (itt.TRANSTYPE IN (0, 2, 3, 8))
AND (invt.INVENTSERIALID <> '')
ORDER BY
itt.RECID DESC) AS C
ON C.ITEMID = a.ITEMID
AND C.INVENTSERIALID = id.INVENTSERIALID
LEFT OUTER JOIN (SELECT TOP (1)
itt2.ITEMID
,invt2.INVENTSERIALID
,itt2.COSTAMOUNTPOSTED AS CostAmtPosted
,itt2.COSTAMOUNTPHYSICAL + itt2.COSTAMOUNTADJUSTMENT AS CostAmtPhysical
,itt2.RECID
FROM
dbo.INVENTTRANS AS itt2 WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS invt2 WITH (NOLOCK)
ON invt2.DATAAREAID = itt2.DATAAREAID
AND invt2.INVENTDIMID = itt2.INVENTDIMID
WHERE
(itt2.DATAAREAID = 'STI')
AND (itt2.TRANSTYPE IN (0, 2, 3, 4, 6, 8))
AND (invt2.INVENTSERIALID <> '')
ORDER BY
itt2.RECID DESC) AS D
ON D.ITEMID = a.ITEMID
AND D.INVENTSERIALID = id.INVENTSERIALID
WHERE
(a.DATAAREAID = 'STI')
AND (a.CLOSED = 0)
AND (a.PHYSICALINVENT > 0)
AND (it.ITEMGROUPID LIKE 'FG-%'
OR it.ITEMGROUPID = 'MULTISHIP')
ORDER BY
SiteId
,Warehouse
Presumably, the top value in the subquery doesn't meet the subsequent join conditions. That is, this condition is not met:
D.ITEMID = a.ITEMID AND D.INVENTSERIALID = id.INVENTSERIALID
You are using a left outer join, so NULL values are filled in.
EDIT:
To re-iterate. When you run it with top 1, there are no values (for at least some combinations of the two variables). So, NULL will be filled in for these values. After all, top 1 (with or without the parentheses) returns only one row.
When you run it returning multiple rows, presumably there are matches. For the rows that match, the corresponding values are put it. This is the way that left outer join works.
Gordon's answer is correct as to why I was getting a few rows when removing top and none when I had it. The subquery in question was returning all the rows in the InventTrans table (5 million+) so when I used top, it was just getting the first row which didn't have anything. I realized this was the case when I was trying random high values (e.g 50000) in the TOP clause.
The ultimate fix was to change the left outer joins on the C and D subqueries to Cross Apply, and then change the where clauses to better filter the table (e.g itt.itemid = a.itemid and invt1.inventserialid = id.inventserialid). Using that, I was able to use TOP 1 as expected.