SELECT bm.WinningNumber,bd.BetOnNumber,"WinLossAmount" =
CASE
WHEN 2 in (2,1) THEN ('WIN')
END
FROM BettingMaster bm inner join BettingDetail bd on bm.GameID = bd.GameID
where bd.GameID = 1
This works as a Charm and I get 'WIN' in WinLossAmount. Now I actually have value 2 in column WinningNumber(varchar) and value 2,1 in column BetOnNumber(varchar). I retried the statement as
SELECT bm.WinningNumber,bd.BetOnNumber,"WinLossAmount" =
CASE
WHEN bm.WinningNumber in (bd.BetOnNumber) THEN ('WIN')
END
FROM BettingMaster bm inner join BettingDetail bd on bm.GameID = bd.GameID
where bd.GameID = 1
This doesn't work. Is it not possible this way?! Any help??
IN operator in SQL searches values in the row set. But in the second example you try to find INT value in the STRING so you can't use IN this way.
In the most SQL systems you can try to use following condition. Where + is a concatenate operator in MSSQL (in Oracle ||, in MySQL CONCAT())
WHEN ','+bd.BetOnNumber+',' LIKE '%,'+CAST(bm.WinningNumber AS VARCHAR(10))+',%'
THEN ...
Also in MySQL you can use FIND_IN_SET() function:
WHEN FIND_IN_SET(bm.WinningNumber,bd.BetOnNumber) THEN ...
PS: Both ways can't use indexes so you shouldn't use them on big tables.
I believe the problem is that in the first statement, SQL is comparing 2 to 1 and then 2 to 2, all integers. Obviously, finding the match and working.
In the second case, you're comparing 2 to a string of "1,2" and 2 does not equal "1,2". You'll need to split the varchar into a series of integers before you compare it. Take a look at:
Parse comma-separated string to make IN List of strings in the Where clause
This should help you out.
You can't just use IN and then specify a column name, you need to use a subquery:
SELECT bm.WinningNumber ,
bd.BetOnNumber ,
"WinLossAmount" = CASE WHEN bm.WinningNumber IN (
SELECT bd.BetOnNumber
FROM BettingMaster bm
INNER JOIN BettingDetail bd ON bm.GameID = bd.GameID
WHERE bd.GameID = 1 ) THEN ( 'WIN' )
END
FROM BettingMaster bm
INNER JOIN BettingDetail bd ON bm.GameID = bd.GameID
WHERE bd.GameID = 1
Related
I am creating an SQL function to report, the parameters I receive are several strings containing the PK separated by , example:
#ID_Model_list = '1,2'
#ID_Station_list = '1,4,7,8,10'
in my SQL query I perform a subquery, with it I convert the variables I receive into a column, example:
SELECT CAST(VALUE AS INT) AS ID FROM string_split(#ID_Model_list,',')
would be the same as: SELECT CAST(value AS int) AS ID FROM string_split('1,2',',')
Result:
If I add the code above to my query, it only takes the first value of the column that results from the subquery
CREATE FUNCTION V_Scrap_Report
(#ID_Model_list varchar, #ID_Station_list varchar, #fecha datetime, #fechafin datetime)
RETURNS TABLE
AS RETURN
(SELECT S.IDScrap
, S.fecha
, M.modelo
, E.estacion
, C.correccion
, S.elemento
, P.nombre
, P.numeroparte
, Sp.cantidad
FROM dbo.Scrap S
FULL OUTER JOIN dbo.Modelo M ON S.IDModelo = M.IDModelo
FULL OUTER JOIN dbo.Estacion E ON E.IDEstacion = S.IDEstacion
FULL OUTER JOIN dbo.Scrapcorreccion Sc ON S.IDScrap = Sc.IDScrap
FULL OUTER JOIN dbo.Correccion C ON C.IDCorrecion = Sc.IDCorrecion
FULL OUTER JOIN dbo.Scraparte Sp ON S.IDScrap = Sp.IDScrap
JOIN dbo.Parte P ON Sp.IDParte = P.IDParte
WHERE S.fecha >= #fecha
AND S.fecha <= DATEADD(HOUR,23.9999,#fechafin)
AND S.IDModelo = (SELECT CAST(VALUE AS INT) AS ID FROM string_split(#ID_Model_list,','))
AND S.IDEstacion = (SELECT VALUE FROM string_split(#ID_Station_list,',')))
The above function is only returning results when S.IDModelo = 1 AND S.IDEstacion = 1 does not take into account that there is:
S.IDModelo = 2 AND S.IDEstacion = 1
S.IDModelo = 1 AND S.IDEstacion = 4
S.IDModelo = 1 AND S.IDEstacion = 7
S.IDModelo = 1 AND S.IDEstacion = 8
S.IDModelo = 2 AND S.IDEstacion = 10
When I call the function I do it like this:
SELECT * FROM V_Scrap_Report('1,2','1,4,7,8,10','2022-07-18','2022-07-20')
oddish, if i change ... V_Scrap_Report('1,2'... by ... V_Scrap_Report('2,1'... just bring
S.IDModelo = 2 AND S.IDEstacion = 1
what could be missing in the query so as not to skip matches?
The comments and Bohemian's answer give you a few specific things that are wrong with your query that you need to look at, but I think what you really need is a different understanding of what you're doing. So...
A select returns a set. (Technically a bag because it can contain duplicates, but we'll ignore that).
A set can have zero members, or one member, or more members. There's a set of integers greater than 1 and less than 4, and that set is {2, 3}. There's a set of integers less than 1 and greater than 4, and that set is {} aka "the empty set".
So a set is a collection of zero or more things, not one thing.
When you're comparing things, you can't compare a collection of things with just one thing. Suppose I have a bag of oranges in my left hand, and one orange in my right hand. Does the orange in my right hand taste the same as the bag of oranges in my left hand? The question doesn't really make sense, does it? You have to compare the one orange in my right hand with each orange in the bag, individually.
So if I ask SQL to evaluate whether orange_in_right_hand = { first_orange_in_bag, second_orange_in_bag, third_orange_in_bag } what do you want it to do? It's a question that doesn't really make sense.
You have a situation like this in your query:
where S.IDEstacion = (SELECT VALUE FROM string_split(#ID_Station_list,',')))
You do a similar comparison with #ID_model_list.
The left hand side of that operation is one value. The right hand side of that operation is the result of a select, which can return more than one value. In this case, the output of the string_split function. You are asking SQL to determine whether the one thing is equal to potentially many things.
This doesn't really make sense as we saw with the oranges. And because it doesn't make sense, it will actually cause an error.
So why aren't you getting an error? Because in your specific case, the set returned by string_split will happen to only have one member, because you have a bug in the code.
Let's look at #ID_station_list. Your input to the string_split is the #ID_Station_list parameter, which you have said is a varchar. But you didn't say how long it is. In this case, that means it will be treated as being one character long:
declare #ID_station_list varchar;
set #ID_station_list = '1,4,7,8,10';
select #ID_station_list;
What do you think this will return? It will return the string value '1'. All of the other characters got thrown away, because you didn't say #ID_station_list was a varchar big enough to hold the value you gave it. You just said it was a varchar, and SQL will assume you meant varchar(1) in this case.
So the value you are passing to string_split function is just the value '1'. So you get one value back when you split this string.
SQL Server will then look at that and think "well, ok, you are asking me whether a single value is equal to the result of a select, which you really shouldn't be doing because it doesn't make sense, but in this particular case I will do it for you without telling you the problem because there was only one member in the set".
If you fix your parameter declaration by, say, making #ID_station_list a varchar(100) and giving it the value '1,2,3', you'll get an error.
So how should you compare the single value IDEstacion with the set returned by string_split? You tell SQL to check whether the value is in the set instead of checking whether it equals the set. Hence Stu's comment.
If you put where clause conditions on an outer joined table, you effectively convert the join to an inner join.
Move such conditions to the join condition:
...
FROM dbo.Scrap S
FULL OUTER JOIN dbo.Modelo M ON S.IDModelo = M.IDModelo
AND S.IDModelo = (SELECT CAST(VALUE AS INT) AS ID FROM string_split(#ID_Model_list,','))
FULL OUTER JOIN dbo.Estacion E ON E.IDEstacion = S.IDEstacion
AND S.IDEstacion = (SELECT VALUE FROM string_split(#ID_Station_list,',')))
FULL OUTER JOIN dbo.Scrapcorreccion Sc ON S.IDScrap = Sc.IDScrap
FULL OUTER JOIN dbo.Correccion C ON C.IDCorrecion = Sc.IDCorrecion
FULL OUTER JOIN dbo.Scraparte Sp ON S.IDScrap = Sp.IDScrap
JOIN dbo.Parte P ON Sp.IDParte = P.IDParte
WHERE S.fecha >= #fecha
AND S.fecha <= DATEADD(HOUR,23.9999,#fechafin)
I have a column where I have 0 or 1. I like to do the following set up:
If 0 than put / use the Region_table (here I have regions like EMEA, AP,LA with finished goods only) and when it 1 then put / use the Plant_table (here I have plants with non-finished goods) data's.
I tried to write it in 2 different statements but it is not good:
,Case
when [FG_NFG_Selektion] = '0' Then 'AC_region'
End as 'AC_region'
,Case
when [FG_NFG_Selektion] = '1' Then 'AC_plant'
End as 'AC_plant'
I'm not 100% clear on what you're looking for, but if you want to get data from different tables based on the value in the [FG_NFG_Selektion] field, you can do something like this:
SELECT
CASE
WHEN [FG_NFG_Selektion] = '0' THEN r.some_col -- If 0, use value from "region" table
WHEN [FG_NFG_Selektion] = '1' THEN p.some_col -- If 1, use value from "plant" table
END AS new_field
FROM MyTable t
LEFT JOIN AC_region r ON t.pk_col = r.pk_col -- get data from "AC_region" table
LEFT JOIN AC_plant p ON t.pk_col = p.pk_col -- get data from "AC_plant" table
;
If [FG_NFG_Selektion] is a numeric field, then you should remove the single quotes: [FG_NFG_Selektion] = 0.
I would strongly recommend putting the conditions in the ON clauses:
SELECT COALESCE(r.some_col, p.some_col) as som_col
FROM t LEFT JOIN
AC_region r
ON t.pk_col = r.pk_col AND
t.FG_NFG_Selektion = '0' LEFT JOIN
AC_plant p
ON t.pk_col = p.pk_col AND
t.FG_NFG_Selektion = '1';
Why do I recommend this? First, this works correctly if there are multiple matches in either table. That is probably not an issue in this case, but it could be in others. You don't want to figure out where extra rows come from.
Second, putting the conditions in the ON clause allows the optimizer/execution engine to take advantage of them. For instance, it is more likely to use FG_NFG_Selektion in an index.
I need to select some columns from two tables in a SQL Server database. I need to use something like the following:
SELECT
c.itmtxt, a.attr1val, a.attr2val, a.attr3val
FROM
code c
JOIN
codeattribute a ON c.itmcd = a.itmcd
WHERE
c.catcd = 1
AND c.itmtxt = 2
AND a.attr1val = 'A'
However, when I add the last where AND statements the query does not work. If I end with the single WHERE clause the code works as expected.
Can anyone see what is wrong?
Thanks!
You'll need to move AND a.attr1val = 'A' into your join clause.
SELECT c.itmtxt, a.attr1val, a.attr2val, a.attr3val FROM code c
JOIN codeattribute a ON c.itmcd = a.itmcd AND a.attr1val = 'A'
WHERE c.catcd = 1
AND c.itmtxt = 2
SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo != h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = 1
I'm trying to figure out if there's a possibility to get the h.cd_turnovalue from another table and use in the same query, beacuse this value is gonna be variable. So, I'd have to get this value from a query, then pass the value to PHP and do another query with this value. Is there a way to do that in the same query?
There's a table called turmas(codigo, cd_turno). I'll have the codigovalue, in this case HTJ009, and I'd like to select the cd_turno value.
Query used to get the value:
SELECT cd_turno FROM turmas WHERE codigo='HTJ009'
You can use a subquery, like so:
SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo != h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = (SELECT cd_turno FROM turmas WHERE codigo='HTJ009')
In this case, remember that it is important for the subquery to return only one result, otherwise you'll encounter an error. If you do see such an error, you may have to tweak the subquery to ensure only one result is returned.
Check this out for Postgres subquery documentation
SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo = h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = 1 and h_t.cd_horario is null
this is an attempted fix to a crystal reports use of 2 sub reports!
I have a query that joins 3 tables, and I wanted to use a pair of sub selects that bring in the same new table.
Here is the first of the two columns in script:
SELECT ea."LOC_ID", lo."DESCR", ea."PEGSTRIP", ea."ENTITY_OWNER"
, ea."PCT_OWNERSHIP", ea."BEG_BAL", ea."ADDITIONS", ea."DISPOSITIONS"
, ea."EXPLANATION", ea."END_BAL", ea."NUM_SHARES", ea."PAR_VALUE"
, ag."DESCR", ea."EOY", ea."FAKEPEGSTRIP",
(select sum(htb.END_FNC_CUR_US_GAAP)
from EQUITY_ACCOUNTS ea , HYPERION_TRIAL_BALANCE htb
where
htb.PEGSTRIP = ea.PEGSTRIP and
htb.PRD_NBR = 0 and
htb.LOC_ID = ea.LOC_ID and
htb.PRD_YY = ea.EOY
) firstHyp
FROM ("TAXPALL"."ACCOUNT_GROUPING" ag
INNER JOIN "TAXP"."EQUITY_ACCOUNTS" ea
ON (ag."ACCT_ID"=ea."PEGSTRIP") AND (ag."EOY"=ea."EOY"))
INNER JOIN "TAXP"."LOCATION" lo ON ea."LOC_ID"=lo."LOC_ID"
WHERE ea."EOY"=2009
ORDER BY ea."LOC_ID", ea."PEGSTRIP"
When this delivers the dataset the value of "firstHyp" fails to change by pegstrip value. It returns a single total for the join and fails to put the proper by value by pegstrip.
I thought that the where clause would have picked up the joins line by line.
I don't do Oracle syntax often so what am I missing here?
TIA
Your SQL is equivilent to the following:
SELECT ea."LOC_ID", lo."DESCR", ea."PEGSTRIP",
ea."ENTITY_OWNER" , ea."PCT_OWNERSHIP",
ea."BEG_BAL", ea."ADDITIONS", ea."DISPOSITIONS" ,
ea."EXPLANATION", ea."END_BAL", ea."NUM_SHARES",
ea."PAR_VALUE" , ag."DESCR", ea."EOY", ea."FAKEPEGSTRIP",
(select sum(htb.END_FNC_CUR_US_GAAP)
from EQUITY_ACCOUNTS iea
Join HYPERION_TRIAL_BALANCE htb
On htb.PEGSTRIP = iea.PEGSTRIP
and htb.LOC_ID = iea.LOC_ID
and htb.PRD_YY = iea.EOY
where htb.PRD_NBR = 0 ) firstHyp
FROM "TAXPALL"."ACCOUNT_GROUPING" ag
JOIN "TAXP"."EQUITY_ACCOUNTS" ea
ON ag."ACCT_ID"=ea."PEGSTRIP"
AND ag."EOY"=ea."EOY"
JOIN "TAXP"."LOCATION" lo
ON ea."LOC_ID"=lo."LOC_ID"
WHERE ea."EOY"=2009
ORDER BY ea."LOC_ID", ea."PEGSTRIP"
Notice that the subquery that generates firstHyp is not in any way dependant on the tables in the outer query... It is therefore not a Correllated SubQuery... meaning that the value it generates will NOT be different for each row in the outer query's resultset, it will be the same for every row. You need to somehow put something in the subquery that makes it dependant on the value of some row in the outer query so that it will become a correllated subquery and run over and over once for each outer row....
Also, you mention a pair of subselects, but I only see one. Where is the other one ?
Use:
SELECT ea.LOC_ID,
lo.DESCR,
ea.PEGSTRIP,
ea.ENTITY_OWNER,
ea.PCT_OWNERSHIP,
ea.BEG_BAL,
ea.ADDITIONS,
ea.DISPOSITIONS,
ea.EXPLANATION,
ea.END_BAL,
ea.NUM_SHARES,
ea.PAR_VALUE,
ag.DESCR,
ea.EOY,
ea.FAKEPEGSTRIP,
NVL(SUM(htb.END_FNC_CUR_US_GAAP), 0) AS firstHyp
FROM TAXPALL.ACCOUNT_GROUPING ag
JOIN TAXP.EQUITY_ACCOUNTS ea ON ea.PEGSTRIP = ag.ACCT_ID
AND ea.EOY = ag.EOY
AND ea.EOY = 2009
JOIN TAXP.LOCATION lo ON lo.LOC_ID = ea.LOC_ID
LEFT JOIN HYPERION_TRIAL_BALANCE htb ON htb.PEGSTRIP = ea.PEGSTRIP
AND htb.LOC_ID = ea.LOC_ID
AND htb.PRD_YY = ea.EOY
AND htb.PRD_NBR = 0
GROUP BY ea.LOC_ID,
lo.DESCR,
ea.PEGSTRIP,
ea.ENTITY_OWNER,
ea.PCT_OWNERSHIP,
ea.BEG_BAL,
ea.ADDITIONS,
ea.DISPOSITIONS,
ea.EXPLANATION,
ea.END_BAL,
ea.NUM_SHARES,
ea.PAR_VALUE,
ag.DESCR,
ea.EOY,
ea.FAKEPEGSTRIP,
ORDER BY ea.LOC_ID, ea.PEGSTRIP
I agree with Charles Bretana's assessment that the original SELECT in the SELECT clause was not correlated, which is why the value never changed per row. But the sub SELECT used the EQUITY_ACCOUNTS table, which is the basis for the main query. So I removed the join, and incorporated the HYPERION_TRIAL_BALANCE table into the main query, using a LEFT JOIN. I wrapped the SUM in an NVL rather than COALESCE because I didn't catch what version of Oracle this is for.