"Having" in SQL - sql

I have a SQL like this below
SELECT A.UNIT, A.PO_NO, A.LINE, A.QUNATITY,
SUM(B.RECEIVED_QUNATITY) AS "RECEIVED QUANTITY"
FROM PO_TBL A, RECEIVER_TBL B
WHERE A.UNIT = B.UNIT AND A.PO_NO = B.PO_NO AND A.LINE = B.LINE
GROUP BY A.UNIT, A.PO_NO, A.LINE, A.QUNATITY
HAVING ((A.QUNATITY - SUM(B.RECEIVED_QUNATITY)) > 0);
The above SQL return more rows if the Having function is not used and returns null rows, when we using Having function. Even though, Quantity has value as "10" and RECEIVED_QUNATITY has value as "0", that rows are not shown in the output.
Kindly help me on this scenario......

Try this one.
I just place isnull function to check null values.
SELECT A.UNIT, A.PO_NO, A.LINE, A.QUNATITY,
SUM(B.RECEIVED_QUNATITY) AS "RECEIVED QUANTITY"
FROM PO_TBL A, RECEIVER_TBL B
WHERE A.UNIT = B.UNIT AND A.PO_NO = B.PO_NO AND A.LINE = B.LINE
GROUP BY A.UNIT, A.PO_NO, A.LINE, A.QUNATITY
HAVING ((A.QUNATITY - isnull(SUM(B.RECEIVED_QUNATITY),0)) > 0);
Assuming A.Quantity doesn't have null values or else implement isnull over it also.

Related

Oracle SQL - Case statement with iteration

The ASCII table values should be compared to the s.manure_type. For each record in the following table below the QuantityText case statement should do a comparison. The value it needs to select is e.g. oats,velvet beans, other none.
select
c.id customer_num,
c.type type,
s.id_text sample_num,
c.sasa_grower_code s_grower,
c.address s_address1,
c.postalcode s_post_code,
c.email q1_email,
nvl(c.client_name, c.farm_name )s_company,
c.farm_name s_estate,
c.contact_name s_contact,
s.id_numeric id_numeric,
s.id_text fas_lab_id,
s.date_received received_date,
s.date_printed printed_date,
s.sampled_date sampled_date,
e.name S_AREA_DESCRIP,
a.name s_advisor_name,
a.email s_advisor_email,
s.order_no s_order_num,
s.field_name s_field,
p.phrase_text || ' cm' sample_depth,
cr.crop_name s_crop,
s.attyield s_yield,
s.variety s_varty,
case when s.flg_trashed is null then
'None'
else (case when s.flg_trashed = constant_pkg.get_true then
'Yes'
else (case when s.flg_trashed = constant_pkg.get_false then
'No'
else ' '
end)
end) end trashed,
case when s.flg_irrigated is null then
'None'
else (case when s.flg_irrigated = constant_pkg.get_true then
'Yes'
else (case when s.flg_irrigated = constant_pkg.get_false then
'No'
else ' '
end)
end) end s_irrig,
CASE
WHEN trim(s.manure_type) in (select p.phrase_id from phrase p where p.phrase_type = 'AL_G_MANUR') then (select p.phrase_text from phrase p)
END AS QuantityText,
'' S_GM_YIELD,
s.project_code project_code,
s.trial_ref trial_ref,
s.cost_centre cost_centre
from client c
left outer join sample s on (s.client_id = c.id)
left outer join extension e on (e.id = c.extension_id)
left outer join advisor a on (a.id = c.advisor_id)
left outer join phrase p on (p.phrase_id = s.depth)
left outer join crop cr on (cr.id = s.crop_id)
where p.phrase_type = phrase_pkg.get_soil_depth
and c.id = '211493A'
and s.fas_sample_type = sample_pkg.get_soil_sample
and s.flg_recommendation = sample_pkg.get_flg_recommendation
and s.id_numeric between 14932 and 14933
+----------------------------+
| Phrase |
+----------------------------+
|AL_G_MANUR OA Oats |
|AL_G_MANUR V Velvet Beans
|AL_G_MANUR O Other
|AL_G_MANUR N None |
+----------------------------+
But I get the error ORA-00900: Single row query returns more than one row
Missing where clause in one of the case statements is most likely the cause.
CASE
WHEN trim(s.manure_type) in
(select p.phrase_id from phrase p where p.phrase_type = 'AL_G_MANUR')
then (select p.phrase_text from phrase p) <<< NO WHERE CLAUSE ?
END AS QuantityText,
This is relatively easy to debug yourself.
Remove a single selected column
Check if error still occurs
If it does, go back to 1.
If it does not then verify why last added column errors
Problem is in the following statement
then (select p.phrase_text from phrase p)
I guess, It should be replaced with this
(select p.phrase_text from phrase p where p.phrase_type = 'AL_G_MANUR')

SQL Combining Two Totally seperate tables to one

I am VERY new to SQL and self taught. I have two SQL that I stuggled through but got working. Now I need to combine them into one and I'm lost.
SELECT
s.lastfirst,
s.student_number,
SUM(tr.howmany)
FROM
students s
JOIN
truancies tr ON s.id = tr.studentid
WHERE
s.enroll_status = 0 AND
s.schoolid = ~(curschoolid)
GROUP BY
s.lastfirst, s.student_number
HAVING
SUM(tr.howmany) > 0
ORDER BY
s.lastfirst
And this table:
SELECT
S.DCID as DCID,
S.LASTFIRST as LASTFIRST,
S.STUDENT_NUMBER as STUDENT_NUMBER,
S2.FC_SRVC_HRS_DUE as FC_SRVC_HRS_DUE,
CASE
WHEN S2.FC_SRVC_HRS_COMPLETED IS NULL
THEN '0'
ELSE S2.FC_SRVC_HRS_COMPLETED
END AS FC_SRVC_HRS_COMPLETED,
S2.FC_SRVC_HRS_BUYOUT as FC_SRVC_HRS_BUYOUT,
CASE
WHEN S2.FC_SRVC_HRS_COMPLETED IS NULL
THEN S2.FC_SRVC_HRS_DUE * S2.FC_SRVC_HRS_BUYOUT
ELSE ((S2.FC_SRVC_HRS_DUE - S2.FC_SRVC_HRS_COMPLETED) * S2.FC_SRVC_HRS_BUYOUT)
END as Balance_Due
FROM
STUDENTS S, U_STUDENTSUSERFIELDS S2
WHERE
S.DCID = S2.STUDENTSDCID AND
s.enroll_status = 0 AND
s.schoolid = ~(curschoolid) AND
(((S2.FC_SRVC_HRS_DUE - S2.FC_SRVC_HRS_COMPLETED) * S2.FC_SRVC_HRS_BUYOUT) > 0 OR
((S2.FC_SRVC_HRS_DUE - S2.FC_SRVC_HRS_COMPLETED) * S2.FC_SRVC_HRS_BUYOUT) IS NULL) AND
S2.FC_SRVC_HRS_DUE >.1
ORDER BY
s.lastfirst
What I am really looking for are the totals of both of these. I want the SUM(tr.howmany) from the first table and the balance due of the second BUT I need the filters that are in there. This would be sorted by student. I hope I am making sense. Any assistance would be appreciated.
You can join together 2 separate SQL select statements:
Eg:
Select A.id, A.value, B.value
From (select id, count(*) as value from TableA ...) AS A
join (select id, sum(field) as value from TableB ...) AS B
on A.id = B.id
order by A.id
As long as you have a common field to join on this would work. In your case the student_number looks like a good candidate. You will have to do the ordering outside of your subqueries.

QUERY SQL WITH JOIN

I need help about merge 2 query.
QUERY 1:
SELECT anag.Negozio,anag.NomeNegozio,
ISNULL(SUM(ven.Quantita), 0) as PezziVenduti,
ISNULL(SUM(ven.Valore*ven.Quantita), 0) as TotaleVendite
FROM Dylog_NOL_Anagrafica AS anag
LEFT JOIN Dylog_NOL_Movimento AS ven ON anag.IDAnagrafica=ven.IDAnagrafica AND ven.TipoMovimento='VE'
WHERE anag.PortalID=709 AND anag.Negozio IN ('02', '01')
GROUP BY anag.Negozio, anag.NomeNegozio
HAVING ISNULL(SUM(ven.Quantita), 0)<>0
RESULT:
NEGOZIO|NOMENEGOZIO |PezziVenduti|TOTALE VENDITE
01|SEDE PRINCIPALE| 2| 51,78
QUERY 2
SELECT anag.Negozio,anag.NomeNegozio,
ISNULL(SUM(res.Quantita), 0) as PezziResi,
ISNULL(SUM(res.Valore*res.Quantita), 0) as TotaleResi
FROM Dylog_NOL_Anagrafica AS anag
LEFT JOIN Dylog_NOL_Movimento AS res ON anag.IDAnagrafica=res.IDAnagrafica AND res.TipoMovimento='RC'
WHERE anag.PortalID=709 AND anag.Negozio IN ('02', '01')
GROUP BY anag.Negozio, anag.NomeNegozio
HAVING ISNULL(SUM(res.Quantita), 0)<>0
Result:
NEGOZIO|NOMENEGOZIO |PEZZIRESI|TOTALERESI
01|SEDE PRINCIPALE| 1| 25,89
MERGE:
SELECT DISTINCT anag.Negozio,anag.NomeNegozio,
ISNULL(SUM(ven.Quantita), 0) as PezziVenduti,
ISNULL(SUM(ven.Valore*ven.Quantita), 0) as TotaleVendite,
ISNULL(SUM(res.Quantita), 0) as PezziResi,
ISNULL(SUM(res.Valore*res.Quantita), 0) as TotaleResi
FROM Dylog_NOL_Anagrafica AS anag
LEFT JOIN Dylog_NOL_Movimento AS ven ON (anag.IDAnagrafica=ven.IDAnagrafica AND ven.TipoMovimento='VE')
LEFT JOIN Dylog_NOL_Movimento AS res ON (anag.IDAnagrafica=res.IDAnagrafica AND res.TipoMovimento='RC')
WHERE anag.PortalID=709 AND anag.Negozio IN ('02', '01')
GROUP BY anag.Negozio, anag.NomeNegozio
HAVING ISNULL(SUM(ven.Quantita), 0)<>0
OR ISNULL(SUM(res.Quantita), 0)<>0
Result:
NEGOZIO|NOMENEGOZIO |PEZZI VENDUTI|TOTALE VENDITE|**PEZZI RESI|TOTALE RESI**
01|SEDE PRINCIPALE| 2| 51,78| **2| 51,78**
WHY ERROR ON FIELD "PEZZI RESI"? THE CORRECT VALUE IS 1.
Instead of "ISNULL(SUM(ven.Quantita), 0) as PezziVenduti" use "ven.Quantita". Same for the other IsNull entries. This obviously is not what you want but you will allow you to see an extra row that you did not expect. The additional Left join is very likely causing an extra row to summed. You might be able to use one left join and use a case statement in your select to filter the sum on TipoMovimento. Hope this helps
;with Returned_And_Sold as
(
Select ID,
Type,
case when type = 'VE' then isnull(sum(M.Quantity),0) end as QuantitySold,
case when type = 'VE' then isnull(sum(M.Quantity*M.Value),0) end as TotalSold,
case when type = 'RC' then isnull(sum(M.Quantity),0) end as QuantityReturned,
case when type = 'RC' then isnull(sum(M.Quantity*M.Value),0) end as TotalReturned
from dbo.Dylog_NOL_Movimento M
where m.type in ('VE','RC')
group by ID,Type
having isnull(sum(M.Quantity), 0) <> 0
)
select
A.Shop,
A.StoreName,
S.QuantitySold,
S.TotalSold,
S.QuantityReturned,
S.TotalReturned
from Dylog_NOL_Anagrafica A
left JOIN Returned_And_Sold S on
S.ID = A.ID
I think the probelm is OR in
ISNULL(SUM(PezziVenduti), 0) <> 0
OR ISNULL(SUM(PezziResi), 0) <> 0
Based on your logic (IsNull(Sum(..)) you can make it with AND

How to replace a NULL when a COUNT(*) returns NULL in DB2

I have a query:
SELECT A.AHSHMT AS SHIPMENT, A.AHVNAM AS VENDOR_NAME, D.UNITS_SHIPPED, D.ADPON AS PO, B.NUMBER_OF_CASES_ON_TRANSIT, C.NUMBER_OF_CASES_RECEIVED FROM AHASNF00 A
INNER JOIN (SELECT IDSHMT, COUNT(*) AS NUMBER_OF_CASES_ON_TRANSIT FROM IDCASE00 WHERE IDSTAT = '01' GROUP BY IDSHMT) B
ON (A.AHSHMT = B.IDSHMT)
LEFT JOIN (SELECT IDSHMT, (COUNT(*) AS NUMBER_OF_CASES_RECEIVED FROM IDCASE00 WHERE IDSTAT = '10' GROUP BY IDSHMT) C
ON (A.AHSHMT = C.IDSHMT)
INNER JOIN (SELECT ADSHMT, ADPON, SUM(ADUNSH) AS UNITS_SHIPPED FROM ADASNF00 GROUP BY ADSHMT, ADPON) D
ON (A.AHSHMT = D.ADSHMT)
WHERE A.AHSHMT = '540041134';
On the first JOIN statement I have a COUNT(*), on this count sometimes I will get NULL. I need to replace this with a "0-zero", I know think I know how to do it in SQL
ISNULL(COUNT(*), 0)
But this doesn't work for DB2, how can I accomplish this? All your help is really appreciate it.
Wrap a COALESCE around each of the nullable totals in your SELECT list:
SELECT A.AHSHMT AS SHIPMENT,
A.AHVNAM AS VENDOR_NAME,
COALESCE( D.UNITS_SHIPPED, 0 ) AS UNITS_SHIPPED,
D.ADPON AS PO,
COALESCE( B.NUMBER_OF_CASES_ON_TRANSIT, 0 ) AS NUMBER_OF_CASES_ON_TRANSIT,
COALESCE( C.NUMBER_OF_CASES_RECEIVED, 0 ) AS NUMBER_OF_CASES_RECEIVED
FROM ...
The inner joins you're using for expressions B and D mean that you will only receive rows from A that have one or more cases in transit (expression B) and have one or more POs in expression D. Is that the way you want your query to work?
Instead of using ISNULL(COUNT(*), 0),
try using COALESCE(COUNT(*),0)
use IFNULL(COUNT(*), 0) for DB2

create from select(Query error)

create table1 as SELECT from c.Name, Value, Qtr, Value as SUM(Value)
from User.Pofile a,pet_dsa_qtr_table b,User.Count c,User.Service d
WHERE Category = 'PROFESSIONAL' and Item_Name = 'PROF_PKT_RECVD' and
convert(char(32),d.User_Id) = c.Name and Service_Name_Cd = 2
and Status = 2 and d.User_Id *= a.User_Id and c.Period = b.Period
and Module = 'ACCT_TRADES' and Type in ('EQ','OPTN')
GROUP BY Name, Item_Value,
Qtr HAVING SUM(Value) >= 10000 and Item_Value in ('0', NULL);
The above was a query that was created by me as an equivalent for sybase.Can anyone help me in correcting this query
You have some quite serious syntax inconsistencies in your query which I have tried to correct (with guesswork as you haven't provided a table structure). e.g. In the select list you select "Value" but in the GROUP BY you group on "Item_Value" etc.
You also need to fully qualify your columns, some you qualify, some (like "Module" and "Type" etc) you don't.
You might also want to add a storage clause too.
Here is my best educated guess at what you are trying to achieve:
CREATE TABLE table1
AS
SELECT c.Name,
Item_Value,
Qtr,
SUM(Value) as "SUM_Value"
FROM User.Pofile a
pet_dsa_qtr_table b,
User.Count c,
User.Service d
WHERE Category = 'PROFESSIONAL'
AND Item_Name = 'PROF_PKT_RECVD'
AND TO_CHAR(d.User_Id) = c.Name
AND Service_Name_Cd = 2
AND Status = 2
AND d.User_Id = a.User_Id(+)
AND c.Period = b.Period
AND Module = 'ACCT_TRADES'
AND Type in ('EQ','OPTN')
GROUP BY c.Name,
Item_Value,
Qtr
HAVING (SUM(Value) >= 10000
AND NVL(Item_Value, '0') = '0');