How to use exists for a complete list of a product? - sql

This is the query to find out if a particular car has W1, W2, WA, WH conditions. How can I modify my query so that I can get a list of all the cars as yes or no for these conditions?
NOTE: Here, I have put v.[carnumber] = 't8302' but I need a complete list.
SELECT
CASE
WHEN EXISTS (
SELECT co.[alias]
FROM [MTI_TAXI].[vehicle] v
LEFT JOIN [MTI_SYSTEM].[Conditions] co with (nolock) on v.DispatchSystemID = co.DispatchSystemID and (v.Conditions & co.conditionvalue > 0)
WHERE co.[alias] in ('W1', 'W2', 'WA', 'WH') and v.[DispatchSystemID] = 6 and v.[CarNumber] = 't8302')
THEN cast ('Yes' as varchar)
ELSE cast ('No' as varchar)
END AS [WATS]
OUTPUT - ( WATS - No )
But, here are all the cars but I am getting yes to WATS condition which is incorrect
enter image description here

Simply utilizing your provided filters and moving the EXISTS to be used in an OUTER APPLY statement:
SELECT
CASE
WHEN [find_wats].[Found] = 1
THEN 'Yes'
ELSE 'No'
END AS [WATS]
FROM
[MTI_TAXI].[vehicle] AS v
OUTER APPLY (SELECT TOP (1)
1 AS [Found]
FROM
[MTI_SYSTEM].[Conditions] AS co
WHERE
v.DispatchSystemID = co.DispatchSystemID
AND
(v.Conditions & co.conditionvalue > 0)
AND
co.[alias] IN ('W1', 'W2', 'WA', 'WH')
AND
v.[DispatchSystemID] = 6) AS [find_wats];
Using this set up, you can then use [find_wats].[Found] = 1 to determine that your record within the table [MTI_TAXI].[vehicle] found a match in [MTI_TAXI].[Conditions] (using your provided criteria) while still maintaining a single record in your final result set for each record originally in the table [MTI_TAXI].[vehicle].

Use count(*) to assert that there was exactly 1 row found by adding:
group by co.[alias]
having count(*) = 1
So the whole query becomes:
SELECT
CASE
WHEN EXISTS (
SELECT co.[alias]
FROM [MTI_TAXI].[vehicle] v
LEFT JOIN [MTI_SYSTEM].[Conditions] co with (nolock)
on v.DispatchSystemID = co.DispatchSystemID
and (v.Conditions & co.conditionvalue > 0)
WHERE co.[alias] in ('W1', 'W2', 'WA', 'WH')
and v.[DispatchSystemID] = 6
and v.[CarNumber] = 't8302'
group by co.[alias]
having count(*) = 1
) THEN cast ('Yes' as varchar)
ELSE cast ('No' as varchar)
end AS [WATS]

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.

UPDATE using case when exists ( don't get the right result)

i'm trying to update a table that is alimented by 2 flows, the 1st one i have to make FillRateCode (the column i want to update) equal to FillRateCode from BWH_OTC_Order but for the 2nd flow i put it equal to '-1'
this is my script:
use BITS
;with tmp as (
select SalesOrderItemNum, SalesOrderNum, FillRateCode
From
BWH_OTC_Order
INNER JOIN REF_Company Comp
ON (Comp.CompanyCode= BWH_OTC_Order.CompanyCode AND Comp.DivisionCode='TEE')
where RevisedPGIDate is not null
)
UPDATE bits_tee.dbo.DMT_TEE_OTC_OrderFulFill
SET FillRateCode = case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
left outer join tmp
on tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
and tmp.SalesOrderNum = DMT.SalesOrderNum
and this is the result i get
NB BWH_FillRateCode DMT_FillRateCode
124457 NULL NULL
73991 0 0
457507 1 1
28632 -1 -1
4849 2 2
34262 3 3
for nulls the correct resault is to get '-1' in DMT_FillRateCode
any issues?
Thx by advence
You can use ISNULL or COALESCE to replace NULL with something else. Your exists( select 1 from tmp) is pointless since it only checks if there are any rows (so not only related rows).
WITH tmp
AS (SELECT SalesOrderItemNum,
SalesOrderNum,
FillRateCode
FROM BWH_OTC_Order
INNER JOIN REF_Company Comp
ON ( Comp.CompanyCode = BWH_OTC_Order.CompanyCode
AND Comp.DivisionCode = 'TEE' )
WHERE RevisedPGIDate IS NOT NULL)
UPDATE DMT
SET DMT.FillRateCode = ISNULL(tmp.FillRateCode, '-1')
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
LEFT OUTER JOIN tmp
ON tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
AND tmp.SalesOrderNum = DMT.SalesOrderNum
Maybe I'm misinterpreting your question, but if you just want to replace null values with -1 you can use the isnull function
isnull(tmp.FillRateCode,-1) -- I'm guessing the -1 is an int, and not a char '-1'
instead of
case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end

multiple errors in using with function in select statement

I'm having some problems with my select statement. When I try to execute it, it gives 3 errors
Must specify table to select from
An object or column name is missing or empty for SELECT INFO statements. verify each column
has a name. For other statements, look for empty alias names. Aliases defined...
Column name or number of supplied values does not match table definition.
WITH A AS
(SELECT ROW_NUMBER() OVER (ORDER BY
CASE
WHEN #pOrderBy = 'SortByName' THEN colPortAgentVendorNameVarchar
WHEN #pOrderBy = 'SortByCOuntry' THEN colCountryNameVarchar
WHEN #pOrderBy = 'SortByCity' THEN colCityNameVarchar
END,
colPortAgentVendorNameVarchar
) xRow, A.*
FROM
(
SELECT DISTINCT
V.colPortAgentVendorIDInt,
colPortAgentVendorNameVarchar = RTRIM(LTRIM(V.colPortAgentVendorNameVarchar)),
C.colCountryNameVarchar,
Y.colCityNameVarchar,
V.colContactNoVarchar,
V.colFaxNoVarchar,
V.colEmailToVarchar,
V.colWebsiteVarchar,
BR.colBrandIdInt,
PR.colPriorityTinyint,
colBrandCodeVarchar = RTRIM(LTRIM(BR.colBrandCodeVarchar))
FROM dbo.TblVendorPortAgent V
LEFT JOIN TblCountry C ON C.colCountryIDInt = V.colCountryIDInt
LEFT JOIN TblCity Y ON Y.colCityIDInt = V.colCityIDInt
LEFT JOIN tblBrandAirportPortAgent PR ON PR.colPortAgentVendorIDInt = V.colPortAgentVendorIDInt
AND PR.colIsActiveBit = 1
LEFT JOIN TblBrand BR ON BR.colBrandIdInt = PR.colBrandIdInt
AND BR.colIsActiveBit = 1
WHERE V.colIsActiveBit = 1
AND V.colPortAgentVendorNameVarchar LIKE '%'+ #pPortAgentVendor +'%'
AND (PR.colBrandIdInt = #pBrandID OR #pBrandID = 0)
) A
)
INSERT INTO #tempPortAgent
SELECT A.*, IsWithContract = CASE WHEN colContractIdInt IS NULL THEN CAST(0 AS BIT) ELSE CAST(1 AS BIT) END FROM A LEFT JOIN TblContractPortAgent B ON A.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
;WITH QQ AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY Q.colPortAgentVendorIDInt ORDER BY xRow,
ContractStatusOrder,
colDateCreatedDate DESC
)ContractRow,*
FROM
(
SELECT DISTINCT GG.*, B.colContractIdInt, B.colContractStatusVarchar, B.colDateCreatedDate ,
ContractStatusOrder = CASE WHEN B.colContractStatusVarchar = 'Approved' THEN 1 ELSE '2' END
FROM #tempPortAgent GG LEFT JOIN TblContractPortAgent B ON GG.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
) Q
)SELECT * INTO #tempPortAgentWithContract
SELECT * FROM #tempPortAgentWithContract
I don't really know where its showing, because the errors are saying that these are inside the select statements inside.
1- Use Select Into instead of Insert into select
SELECT A.*, IsWithContract = CASE WHEN colContractIdInt IS NULL THEN CAST(0 AS BIT) ELSE CAST(1 AS BIT) END
Into #tempPortAgent
FROM A
LEFT JOIN TblContractPortAgent B ON A.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
2- SELECT * INTO #tempPortAgentWithContract is incorrect syntax. you must use following format:
SELECT * INTO #tempPortAgentWithContract From QQ

Trouble with case statement

I am having problems with this case statement. I don't know what I am doing wrong but I get the error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I have a case when the field equals a value then do a left outer join but if the field equals a different value then do a inner join.
This is my query:
SELECT
case
when oqt = '26' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt)and active = 1)
END,
case
when oqt = '31' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM inner join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
where QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt) and active = 1)
END
from tempoq
The case is an expression that must evaluate to a value. The Select statements that you have return multiple values.
It would seem that you're trying to use Case like it's a C# switch? If that's the case, then you're likely better off with an IF ELSE IF construction.
It looks like you want to do something like this rather than using a CASE statement.
DECLARE #t int
-- This would contain your oqt value
SET #t =1
IF #t = 1
BEGIN
SELECT * FROM tableA
END
ELSE IF #t = 2
BEGIN
SELECT * FROM TableB
END
Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM
inner join tempoq on tempoq.oqt = QM.id_oqt
left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE active = 1 and (tempoq.oqt = '26' or (tempoq.oqt = '31' and courseversions.* is not null))
left outer join means join OQMethods's data which even no match data from courseversions,
then filter the data with null courseversions.* that is inner join.
Hope I have the right understanding.

All rows where at least one child has all of its own children pass a condition

I'm having a little trouble with a SQL query, and thought I'd solicit the wisdom of the crowd to see what I'm missing. I'm pretty sure the below works, but it seems really poor and I'm wondering if there's a smarter way (ideally using joins instead of sub-selects) to do this.
The Problem
Let's say I have some tables:
Prize
- PrizeId
RulePrize_Map
- PrizeId
- RuleId
Rule
- RuleId
Conditional
- ConditionalId
- RuleId
- InputId
- ExpectedValue (bit)
Input
- InputId
A Prize is won when at least one Rule is true. A Rule is true when all of its Conditionals are true. A Conditional is "true" when its InputId is either present or not present in the Input table, as designated by the ExpectedValue field. This could perhaps be treated as equivalent to: Count(InputId in Input table) = ExpectedValue for the Conditional's InputId.
Some Examples:
Conditional (InputId = 11, ExpectedValue = 1) -> True if InputId 11 in Input Table
Conditional (InputId = 12, ExpectedValue = 0) -> True if Inputid 12 NOT in Input Table
My Goal
I want to get all Prizes where at least one Rule is "true". I would settle for: "All Rules that are true".
My Attempt
select p.PrizeId from Prize p INNER JOIN RulePrize_Map rpm ON rpm.PrizeId = p.PrizeId
WHERE p.PrizeId IN
(select r.PrizeId from Rule r
where
(select count(*) from Conditional c1 where c1.RuleId = r.RuleId)
=
(select count(*) from Conditional c2
where c2.RuleId = r.RuleId AND
(select count(*) from Input i where i.InputId = c2.InputId) = c2.ExpectedValue
)
)
GROUP BY p.prizeId
The question change a bit, so I have redone the answer...
SELECT
PrizeId
FROM
(
SELECT
PrizeRule_Map.PrizeId,
PrizeRule_Map.RuleId
FROM
PrizeRule_Map
INNER JOIN
Rule
ON Rule.RuleId = PrizeRule_Map.RuleId
INNER JOIN
Conditional
ON Conditional.RuleId = Rule.RuleID
LEFT JOIN
Input
ON Input.InputId = Conditional.InputID
GROUP BY
PrizeRule_Map.PrizeId,
PrizeRule_Map.RuleId
HAVING
COUNT(*) = SUM(CASE Conditional.ExpectedValue
WHEN 1 THEN CASE WHEN Input.InputId IS NULL THEN 0 ELSE 1 END
WHEN 0 THEN CASE WHEN Input.InputId IS NULL THEN 1 ELSE 0 END
END
)
)
AS map
GROUP BY
PrizeId
To get all RuleIds where ALL Conditionals are true:
SELECT r.RuleID
FROM Rule r
JOIN Conditional c
ON c.RuleId = r.RuleId
LEFT JOIN Input i
ON i.InputId = c.InputId
GROUP BY r.RuleID
HAVING COUNT( CASE WHEN (c.ExpectedValue=1) AND (i.InputId IS NOT NULL)
OR (c.ExpectedValue=0) AND (i.InputId IS NULL)
THEN 1
ELSE NULL
END )
= COUNT( * )
Another way - probably slower but it doesn't hurt to test for speed. It doesn't use CASE but the difference (EXCEPT) of two JOINs, only one of them using GROUP BY:
SELECT r.RuleID
FROM Rule r
JOIN Conditional c
ON c.RuleId = r.RuleId
LEFT JOIN Input i
ON i.InputId = c.InputId
WHERE c.ExpectedValue = 1
GROUP BY r.RuleID
HAVING COUNT( i.InputId ) = COUNT( * )
EXCEPT
SELECT r.RuleID
FROM Rule r
JOIN Conditional c
ON c.RuleId = r.RuleId
JOIN Input i
ON i.InputId = c.InputId
WHERE c.ExpectedValue = 0
Try the following:
SELECT Rule.RuleId, Rule.RuleName
FROM Rule
INNER JOIN Conditional ON Rule.RuleId = Conditional.RuleId
Where Conditional.ExpectedValue == true