Create sql query string - sql

i have a problem to create query for table
mouventDeStock
|| idMv || dateMv ||qteMv || typeMV(bit) || codeMv ||
the feild type is either 0 or 1 if 0 means out of the stock , if 1 means means input of stock
i wanna calculate the qte witch is equal to
qte = ( sum(qteMv) where typeMv = 1 ) - ( sum(qteMv) where typeMv = 0 )
how i can't do it in sql
(select sum(mvQte) from mouvementDeStock
where (mvType = 1 and mvCode = 'ART_18'))
-
(select sum(mvQte) from mouvementDeStock
where (mvType = 0 and mvCode = 'ART_18')
but it's not working at all

Try this...
Select Y.S - X.S As Sum from
(select sum(qteMv) S from mouventDeStock where typemv=1 and codemv = 'ART_18') Y,
(select sum(qteMv) S from mouventDeStock where typemv=0 and codemv = 'ART_18') X;

You can use subqueries to calculate the subtotals, but your entire statement must be a valid SQL statement, so you need to wrap another SELECT around them:
SELECT (SELECT SUM(mvQte) FROM mouvementDeStock
WHERE mvType = 1 AND mvCode = 'ART_18')
-
(SELECT SUM(mvQte) FROM mouvementDeStock
WHERE mvType = 0 AND mvCode = 'ART_18')
If you want to be clever, you can do this with a single sum, by making all out-of-stock mvQte values negative by multiplying them with -1:
SELECT SUM(mvQte * CASE mvType WHEN 0 THEN -1 ELSE 1 END)
FROM mouvementDeStock
WHERE mvCode = 'ART_18'
(CASE expression documentation)

Related

Simple way to check % of total if I add one criteria

I have the following script:
select count (*)
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx'
and criteria 3 = 'x'
Is there a nice way to calculate the % of the count with the first 2 criterias vs the count with all 3 criterias ?
So far I'm using something that is not very elegant:
Select x.nb / y.nb
from
(select count (*) as nb
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx'
and criteria 3 = 'x' ) x
JOIN
(select count (*) as nb
from somewhere
where 1=1
and criteria 1 = 'xxx'
and criteria 2 = 'xx' ) y on 1 = 1
Thanks!
You can use avg():
select avg(case when criteria3 = 'x' then 1.0 else 0 end) as ratio
from somewhere
where criteria 1 = 'xxx' and criteria 2 = 'xx' ;
Or more concisely as:
select avg( (criteria3 = 'x')::int ) as ratio
from somewhere
where criteria 1 = 'xxx' and criteria 2 = 'xx' ;

Using a earlier made Column

I'm making a stored procedure where I have declared a column with the AS "NameofColumn" method. Now I want to use that value again later in the stored procedure. Is there anyway to do this?
CASE
WHEN ((select top 1 stuksweergeven from componenten where componentid = componentlink.componentid) = 1) and ((select AmountKG from componenten where componentid = componentlink.componentid) <> 0) THEN
Amount * (select AmountKG from componenten where componentid = componentlink.componentid)
ELSE
Amount
END AS Amount
Now later I want to do the following
Amount * 10 AS TotalAmount
Use subquery where you count the "Amount" and then make select to from that subquery . Something like that:
select Amount * 10 AS TotalAmount from ( SELECT CASE
WHEN ((select top 1 stuksweergeven from componenten where componentid = componentlink.componentid) = 1) and ((select AmountKG from componenten where componentid = componentlink.componentid) <> 0) THEN
Amount * (select AmountKG from componenten where componentid = componentlink.componentid)
ELSE
Amount
END AS Amount FROM yourtable )e

Union different tables with differents columns and data

My problem is that I have 4 differents SELECT with
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
I want that the results appear together whith the respective names like:
regular rptmm new rptss
10 5 2 6
Firstly, I'd suggest not to use Count()*. There are many answers on this site explaining why so I am not going to repeat it.
Instead, I'd suggest you to use a query like this:
SELECT (SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 1) AS 'Regular',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 0) AS 'rptmm',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 0) AS 'New',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 1) AS 'rptss'
Hope this helps!!!
Just put UNION ALL between your four statements you will get four rows with each count on its own row. However, you will lose the column name. You could also use join to get one row with four columnes. Just put the keyword join between each sql statement.
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
JOIN
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
JOIN
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
JOIN
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
You could create a temp table to hold all of this data for you: Replace Name1, Name2, Name3,Name4 with whatever you want to call them. These will be the column headers.
CREATE TABLE #Temp(
NAME1 INT
,NAME2 INT
,NAME3 INT
,NAME4 INT
)
INSERT INTO #Temp
(NAME1)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 1
INSERT INTO #Temp
(NAME2)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 0
INSERT INTO #Temp
(NAME3)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 0
INSERT INTO #Temp
(NAME4)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 1*
SELECT * FROM #Temp

Join Two Select Statements With Different Columns And Condition

I'm not good at asking question, so i'll give an example of what i want to have.
if i = 1 and xi = 0 then
select a,b,c,d,e,f,g where z = 1
elseif i=0 and xi = 1 then
select a,c,f,h,l,n where w = var
elseif i=1 and xi=1 then
select a,b,c,d,e,f,g, where z = 1
union all
select a,c,f,h,l,n where w = var
end if
How can I join the 2 select statement if their columns are not equal and they both have a unique condition?
Based on the conditions you can create derived tables to fetch desired columns and then to get a union of the two tables add null values in column list of derived tables which have less number of columns:
Pseudo code:
select * from
(select a,b,c,d,e,f,g
where z = 1
and 1 = case when i = 1 and xi = 0 then 1
when i = 1 and xi = 1 then 1
else 0
end) as T1
union all
(select a,c,f,h,l,n ,null -- add null value to equate number of columns
where w = var
and 1 = case when i=0 and xi = 1 then 1
when i=1 and xi = 1 then 1
else 0
end) as T2
Hope this helps!!!
If it is not a requirement not to use dynamic sql I will opt for that one.
Another idea will be to use user defined function returnin tables.
So you encapsulate there the logic...

SQL IN or EXISTS clause issue

I have two separate queries that I'd like to combine but I'm struggling to get the result I'd like. One summarizes all the values in the table and another selects duplicate rows based on the most recent date.
A shortened version of the first query is:
SELECT a.PLANT_NO "PlantNumber",
SUM(CASE WHEN a.REC_STATUS_CD = 'RR' THEN -a.KW_CTR_REDELIVERED_HV
ELSE a.KW_CTR_REDELIVERED_HV END) "KeepWholeResidueMMBtu",
SUM(a.ETH_APPLIED_POP_PCT + a.ISO_APPLIED_POP_PCT +
(CASE WHEN a.PLANT_NO = '002' THEN a.ALTLIQ_APPLIED_POP_PCT ELSE 0 END)
)/100 "NGLPOPPaymentPercent"
FROM GAS_STMT a
INNER JOIN SETTLE_SUMMARY c
ON CASE WHEN SUBSTR(a.TRNX_ID,1,1) = '-'
THEN SUBSTR(a.TRNX_ID, 2, LENGTH(a.TRNX_ID))
ELSE CAST(a.TRNX_ID AS VARCHAR2(100))
END = c.TRNX_ID
AND a.MTR_NO||a.MTR_SFX = c.MTR_NO||c.MTR_SFX
WHERE TO_CHAR(a.PROD_DT, 'YYYY') >= TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYY')
AND a.STATUS_UNIT_TM_CD = 'M'
GROUP BY a.PLANT_NO
ORDER BY a.PLANT_NO
The other query is used to filter out four transactions based on the most recent transaction date.
SELECT a.*
FROM GAS_STMT a,
(SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
WHERE a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
I would think that I could use where NOT IN or NOT EXISTS to have the first query sum everything except for those four records excluded in the second query.
Using EXISTS I get the same result as the first query by itself and using NOT EXISTS I get no results. When I use IN I get a sum of the excluded records which is the opposite of what I want.
Is there a good way to do this in PL/SQL? I'm confused that I'm not getting any records for the NOT EXISTS query.
Example of first query results:
Plant_No - Sum
002 - 100
450 - 50
500 - 50
Example of second query results:
Trnx_ID - Plant_no - KW_CTR_REDELIVERED_HV
1234 - 002 - -.99
1235 - 002 - -.99
Intended result:
Plant_No - Sum
002 - 98.02
450 - 50
500 - 50
If you want to exclude the records returned by the second query, try:
SELECT a.PLANT_NO "PlantNumber",
SUM(CASE WHEN a.REC_STATUS_CD = 'RR' THEN -a.KW_CTR_REDELIVERED_HV
ELSE a.KW_CTR_REDELIVERED_HV END) "KeepWholeResidueMMBtu",
SUM(a.ETH_APPLIED_POP_PCT + a.ISO_APPLIED_POP_PCT +
(CASE WHEN a.PLANT_NO = '002' THEN a.ALTLIQ_APPLIED_POP_PCT ELSE 0 END)
)/100 "NGLPOPPaymentPercent"
FROM GAS_STMT a
INNER JOIN SETTLE_SUMMARY c
ON CASE WHEN SUBSTR(a.TRNX_ID,1,1) = '-'
THEN SUBSTR(a.TRNX_ID, 2, LENGTH(a.TRNX_ID))
ELSE CAST(a.TRNX_ID AS VARCHAR2(100))
END = c.TRNX_ID
AND a.MTR_NO||a.MTR_SFX = c.MTR_NO||c.MTR_SFX
LEFT JOIN (SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
ON a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID
AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
WHERE TO_CHAR(a.PROD_DT, 'YYYY') >= TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYY')
AND a.STATUS_UNIT_TM_CD = 'M'
AND b.MTR_NO IS NULL
GROUP BY a.PLANT_NO
ORDER BY a.PLANT_NO
Join b from the second query on to the first query the same way that the second query does it i.e.
inner join (SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
on a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
that way you get everything from the first query but only from the rows that would show up on the second query