Multiple Syntax Use - sql

Please correct my SQL query for use in Oracle:
SELECT *
FROM GNGRB.PRBOOK
WHERE (SERIES = 'I' AND BOOKNO = '180922')
AND (SERIES = 'J' AND BOOKNO = '138446')
AND (SERIES = 'K' AND BOOKNO = '196491')

I got you. You want all records which have either of mentioned combinations.
As mentioned in other answer, use OR or you can use the IN as follows:
SELECT * FROM GNGRB.PRBOOK
WHERE (SERIES,BOOKNO) IN (('I','180922'), ('J', '138446'), ('K', '196491'))

Should you use the OR between the brackets? I am not sure about the use case, but looks like there will never be result from the query, as you are expecting multiple value in same column at same time.
SELECT *
FROM GNGRB.PRBOOK
WHERE (SERIES = 'I' AND BOOKNO = '180922')
OR (SERIES = 'J' AND BOOKNO = '138446')
OR (SERIES = 'K' AND BOOKNO = '196491')

Related

multiple conditions in oracle case with one :PAR

I have a more complex query, but I will give a simple example. In SSRS same input but need different outputs:
select * from myTable where
case
when :PAR1 = 'hour' then myTable.hour = :PAR1
when :PAR1 = 'Mounth' then myTable.Mounth = :PAR1
end
How to make it?
I'm try to
case length(:PAR1)
when 18 then hour: = PAR1
..
always a mistake..
You don't need a CASE expression here:
SELECT *
FROM myTable
WHERE (:PAR1 = 'hour' AND hour = :PAR1) OR
(:PAR1 = 'Mounth' AND Mounth = :PAR1);
Code you posted doesn't make sense to me; are you sure that :PAR1 is used everywhere? I'd expect something like this instead
select *
from mytable
where (:PAR1 = 'hour' and hour = :PAR2)
or (:PAR1 = 'Mounth' and mounth = :PAR2)
-------
maybe not :PAR2, but
certainly not :PAR1
Also, when you're dealing with hours, what is mounth? Shouldn't that be month?

SQL SUM with condition / Invalid column name 'SUM'

I'm trying to make a sum of the variable value/valeur with some conditions but I obtain this error: Invalid column name 'SUM'.
SELECT SUM[value/valeur]
FROM [dbo].[tmp_norm_can]
WHERE [state/etat] = '1000'
AND [geo/geo] = '1'
AND [country/pays] != '999'
I attached an image of the database
Thank you very much!
enter image description here
sum is a function, you need to pass its argument in parentheses:
SELECT SUM([value/valeur])
FROM [dbo].[tmp_norm_can]
WHERE [state/etat] = '1000'
AND [geo/geo] = '1'
AND [country/pays] != '999'
Thank you!
The code that worked was:
SELECT SUM(CAST([value/valeur] AS NUMERIC)) AS "TOTAL", [year/annee] FROM [dbo].[tmp_norm_can] WHERE [state/etat] = '1000' AND [geo/geo] = '1' AND [country/pays] != '999'
Try aliasing your column with a name different than "SUM".

Selection to join the tables VBFA and VBRK

I have done a selection of the table VBFA, that has selected various SD documents based on the code below, and another selection of the table VBRK that has selected the documents that do not have a NETWR = 0. What I want to achieve is to select only those SD documents that are NETWR NE 0.
The code for the selection of the table VBFA is as follows:
SELECT * FROM vbfa AS v INTO TABLE gt_vbfa_inv
FOR ALL ENTRIES IN gt_vbak
WHERE vbelv = gt_vbak-vbeln
AND vbtyp_n IN ('M', 'O', 'P', '5', '6')
AND stufe = '00'
AND NOT EXISTS ( SELECT * FROM vbfa
WHERE vbelv = v~vbeln
AND posnv = v~posnn
AND vbtyp_n IN ('N', 'S')
AND stufe = '00' ) .
And the code for the selection of the VBRK table is as follows:
IF sy-subrc = 0.
SELECT DISTINCT * FROM vbrk
INTO TABLE gt_vbrk
FOR ALL ENTRIES IN gt_vbfa_inv
WHERE vbeln EQ gt_vbfa_inv-vbeln
AND netwr NE 0.
ENDIF.
Is there any way to merge these to two selection via a new Select or a Loop condition, that will select the documents of the table VBFA, where the documents will not have a NETWR = 0 (or NETWR NE 0)?
Thank you all in advance!
My standard approach for converting code using FOR ALL ENTRIES to a JOIN is this.
Convert it to the new SQL syntax with # in front of every variable.
Replace the SELECT * with the fields I actually need. This is important, because JOINs between two tables will always have duplicate field. So SELECT * doesn't work. And it's a bad practice anyway. You almost never need all the fields, so SELECT * is almost always a waste of memory and CPU cycles.
Take both SELECTs and prefix every column name with the table. For example AND stufe = '00' becomes AND vbfa~stufe = '00'
Take the FOR ALL ENTRIES from the second and turn it into a JOIN-condition on the first select. So
FROM vbrk
FOR ALL ENTRIES IN #gt_vbfa_inv
WHERE vbrk~vbeln = #gt_vbfa_inv-vbeln
AND vbrk~netwr <> 0.
becomes
JOIN vbrk
ON vbrk~vbeln = vbfa~vbeln AND
vbrk~netwr <> 0.
Use an inline data declaration for the result-set. That way you don't need to manually create a table- and structure type for holding the results. The end-result would thus look something like this (untested code):
SELECT vbfa~somefield1
vbfa~somefield2
vbfa~somefield3
vbrk~somefield1
vbrk~somefield2
FROM vbfa
JOIN vbrk ON
vbrk~vbeln = vbfa~vbeln AND
vbrk~netwr NE 0.
INTO TABLE #DATA(gt_results)
FOR ALL ENTRIES IN #gt_vbak
WHERE vbfa~vbelv = gt_vbak-vbeln
AND vbfa~vbtyp_n IN ('M', 'O', 'P', '5', '6')
AND vbfa~stufe = '00'
AND NOT EXISTS ( SELECT * FROM vbfa AS vbfa2
WHERE vbfa2~vbelv = vbfa~vbeln
AND vbfa2~posnv = vbfa~posnn
AND vbfa2~vbtyp_n IN ('N', 'S')
AND vbfa2~stufe = '00' ) .
By the way: If gt_vbak comes from a SELECT too, then you likely can integrate this as another join here, too.

how do I join two tables sql

I have an issue that I'm hoping you can help me with. I am trying to create charting data for performance of an application that I am working on. The first step for me to perform two select statements with my feature turned off and on.
SELECT onSet.testName,
avg(onSet.elapsed) as avgOn,
0 as avgOff
FROM Results onSet
WHERE onSet.pll = 'On'
GROUP BY onSet.testName
union
SELECT offSet1.testName,
0 as avgOn,
avg(offSet1.elapsed) as avgOff
FROM Results offSet1
WHERE offSet1.pll = 'Off'
GROUP BY offSet1.testName
This gives me data that looks like this:
Add,0,11.4160277777777778
Add,11.413625,0
Delete,0,4.5245277777777778
Delete,4.0039861111111111,0
Evidently union is not the correct feature. Since the data needs to look like:
Add,11.413625,11.4160277777777778
Delete,4.0039861111111111,4.5245277777777778
I've been trying to get inner joins to work but I can't get the syntax to work.
Removing the union and trying to put this statement after the select statements also doesn't work. I evidently have the wrong syntax.
inner join xxx ON onSet.testName=offset1.testName
After getting the data to be like this I want to apply one last select statement that will subtract one column from another and give me the difference. So for me it's just one step at a time.
Thanks in advance.
-KAP
I think you can use a single query with conditional aggregation:
SELECT
testName,
AVG(CASE WHEN pll = 'On' THEN elapsed ELSE 0 END) AS avgOn,
AVG(CASE WHEN pll = 'Off' THEN elapsed ELSE 0 END) AS avgOff
FROM Results
GROUP BY testName
I just saw the filemaker tag and have no idea if this work there, but on MySQL I would try something along
SELECT testName, sum(if(pll = 'On',elapsed,0)) as sumOn,
sum(if(pll = 'On',1,0)) as numOn,
sum(if(pll ='Off',elapsed,0)) as sumOff,
sum(if(pll ='Off',1,0)) as numOff,
sumOn/numOn as avgOn,
sumOff/numOff as avgOff
FROM Results
WHERE pll = 'On' or pll='Off'
GROUP BY testName ;
If it works for you then this should be rather efficient as you do not need to join. If not, thumbs pressed that this triggers another idea.
The difficulty you have with the join you envisioned is that the filtering in the WHERE clause is performed after the join was completed. So, you would still not know what records to use to compute the averages. If the above is not implementable with FileMaker then check if nested queries work. You would then
SELECT testName, on.avg as avgOn, off.avg as avgOff
FROM ( SELECT ... FROM Results ...) as on, () as off
JOIN on.testName=off.testName
If that is also not possible then I would look for temporary tables.
OK guys... thanks for the help again. Here is the final answer. The statement below is FileMaker custom function that takes 4 arguments (platform, runID, model and user count. You can see the sql statement is specified. FileMaker executeSQL() function does not support nested select statements, does not support IF statements embedded in select statements (calc functions do of course) and finally does not support the SQL keyword VALUES. FileMaker does support the SQL keyword CASE which is a little more powerful but is a bit wordy. The select statement is in a variable named sql and result is placed in a variable named result. The ExecuteSQL() function works like a printf statement for param text so you can see the swaps do occur.
Let(
[
sql =
"SELECT testName, (sum( CASE WHEN PLL='On' THEN elapsed ELSE 0 END)) as sumOn,
sum( CASE WHEN PLL='On' THEN 1 ELSE 0 END) as countOn,
sum( CASE WHEN PLL='Off' THEN elapsed ELSE 0 END) as sumOff,
sum( CASE WHEN PLL='Off' THEN 1 ELSE 0 END) as countOff
FROM Results
WHERE Platform = ?
and RunID = ?
and Model = ?
and UserCnt = ?
GROUP BY testName";
result = ExecuteSQL ( sql ; "" ; ""
; platform
; runID
; model
; userCnt )
];
getAverages ( Result ; "" ; 2 )
)
For those interested the custom function looks like this:
getAverages( result, newList, pos )
Let (
[
curValues = Substitute( GetValue( data; pos ); ","; ¶ );
sumOn = GetValue( curValues; 2 ) ;
countOn = GetValue( curValues; 3 );
sumOff = GetValue( curValues; 4 );
countOff = GetValue( curValues; 5 );
avgOn = sumOn / countOn;
avgOff = sumOff / countOff
newItem = ((avgOff - avgOn) / avgOff ) * 100
];
newList & If ( pos > ValueCount( data); newList;
getAverages( data; If ( not IsEmpty( newList); ¶ ) & newItem; pos + 1 ))
)

change where condition based on column value

I faced the following requirement. The following query is called by a procedure. The value p_pac_code is the input parameter of the procedure.
The requirement is the query should have an additional condition sp_sbsp.SUBSPCLTY_CODE!='C430 if the p_pac_code value is '008'.
For any other p_pac_code value, it should run as it is below. Is there way to do this by adding an additional condition in the WHERE clause?
As for now, I have done this using IF.....ELSE using the query two times separately depending on p_pac_code value. But I am required to find a way to do with just adding a condition to this single query.
SELECT ptg.group_cid
FROM PRVDR_TYPE_X_SPCLTY_SUBSPCLTY ptxss,
PT_X_SP_SSP_STATUS pxsst ,
pt_sp_ssp_x_group ptg,
group_x_group_store gg,
specialty_subspecialty sp_sbsp,
treatment_type tt,
provider_type pt
WHERE
pt.PRVDR_TYPE_CODE = ptxss.PRVDR_TYPE_CODE
AND tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE
AND ptxss.PRVDR_TYPE_X_SPCLTY_SID = pxsst.PRVDR_TYPE_X_SPCLTY_SID
AND tt.TRTMNT_TYPE_CODE = p_pac_code
AND TRUNC(SYSDATE) BETWEEN TRUNC(PXSST.FROM_DATE) AND TRUNC(PXSST.TO_DATE)
AND ptg.prvdr_type_code =ptxss.prvdr_type_code
AND ptg.spclty_subspclty_sid = ptxss.spclty_subspclty_sid
AND ptxss.spclty_subspclty_sid = sp_sbsp.spclty_subspclty_sid
AND ptg.spclty_subspclty_sid = sp_sbsp.spclty_subspclty_sid
AND ptg.status_cid = 2
AND ptg.group_cid = gg.group_cid
AND gg.group_store_cid = 16
AND gg.status_cid = 2;
Thanks in advance.
You can simply add a condition like this:
... and (
( sp_sbsp.SUBSPCLTY_CODE!='C430' and p_pac_code = '008')
OR
NVL(p_pac_code, '-') != '008'
)
This can be re-written in different ways, this one is quite self-explanatory
Just add:
AND NOT ( NVL( sp_sbsp.SUBSPCLTY_CODE, 'x' ) = 'C430'
AND NVL( p_pac_code value, 'x' ) = '008' )
to the where clause.
The NVL function is used so that it will match NULL values (if they exist in your data); otherwise, even though NULL does not match C430 you will still find that NULL = 'C430' and NULL <> 'C430' and NOT( NULL = 'C430' ) will all return false.
Quite easy. Add the following condition:
AND (sp_sbsp.SUBSPCLTY_CODE != 'C430' OR p_pac_code value != '008')
(don't forget the parenthesis)
Just sharing
SELECT ptg.group_cid
FROM PRVDR_TYPE_X_SPCLTY_SUBSPCLTY ptxss
WHERE
pt.PRVDR_TYPE_CODE = ptxss.PRVDR_TYPE_CODE
&&((tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE)
or (tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE))
just use the parenthesis to specify where the conditionmust implement.