Hi, I have this code with missing Criteria - snowflake-cloud-data-platform

[![First output][1]][1]
[![Second output][2]][2]
[![Combined Output][3]][3]
[![Combined Script][4]][4]
I have this code, but the Criteria in "R" (LN-5360) do not exist. However, the criteria in "S" does exist with a sum value of '30'. But when I join both queries it is giving me the "MonthlyPremium" as '0' instead of '30'. Can someone please tell me what I am doing wrong? I can't remove "R" because I have more existing criteria.
Select S.Newf, zeroifnull(Round(PR + PRE)) AS MonthlyPremium
From
(
SELECT TARGET_QUIKPLANSurv.FORM, Ifnull(TARGET_NEWQUIKVALFSurDec.MVALDATE, '2020-12-31') AS ReportDate ,(SUM(TARGET_NEWQUIKVALFSurDec.MANNLZD)/12) AS PR
from TARGET_QUIKPLANSurv Left JOIN TARGET_NEWQUIKVALFSurDec ON TARGET_QUIKPLANSurv.PLAN=TARGET_NEWQUIKVALFSurDec.NPLAN
GROUP BY TARGET_QUIKPLANSurv.FORM, TARGET_NEWQUIKVALFSurDec.MVALDATE
HAVING ((TARGET_QUIKPLANSurv.FORM)='LN-5360')
) as R
Right Join
(
SELECT TARGET_QUIKPLAN.FORMS, Ifnull(TARGET_NEWQUIKVALF1.MVALDATE, '2020-12-31') AS ReportDate ,(SUM(TARGET_NEWQUIKVALF1.MANNLZD)/12) AS PRE,
iff(TARGET_QUIKPLAN.FORMS='L-5360','LN-5360', TARGET_QUIKPLAN.FORMS ) As Newf
from TARGET_QUIKPLAN Left JOIN TARGET_NEWQUIKVALF1 ON TARGET_QUIKPLAN.PLAN=TARGET_NEWQUIKVALF1.NPLAN
GROUP BY TARGET_QUIKPLAN.FORMS, TARGET_NEWQUIKVALF1.MVALDATE
HAVING ((TARGET_QUIKPLAN.FORMS)='L-5360')
) as S on R.FORM = S.Newf
[1]: https://i.stack.imgur.com/2L0MO.png
[2]: https://i.stack.imgur.com/VkPca.png
[3]: https://i.stack.imgur.com/MO1uX.png
[4]: https://i.stack.imgur.com/LFJYS.png

Given you have a value on the S (of 30 as you note) side, and you are doing a RIGHT JOIN you have a row. Time to learn how the different operations you are using work and thus where does the 0 comes from:
SELECT pr
,pre
,pr + pre AS a
,round(a) AS ra
,ZEROIFNULL(ra) as monthlypremium
FROM VALUES
(0,30),
(null,30),
(0,null),
(null,null)
v(pr,pre);
so this is 4 rows of data, with different permutations of results, really the last would not happen.
PR PRE A RA MONTHLYPREMIUM
0 30 30 30 30
null 30 null null 0
0 null null null 0
null null null null 0
So this tells us addition with a null is null, therefore you need to move the ZEROIFNULL to prior of the addition. Thus you want:
ROUND(ZEROIFNULL(pr) + ZEROIFNULL(pre)) AS monthlypremium
As a side note putting your SQL select on new lines makes it easier to read on StackOverflow, and using aliases for your tables, makes reading faster, and given case of columns does not matter, having reserve words and column different case helps comprehension also. I also tend to indent ON and follow WHERE clauses just so you can wrap things onto new lines to keep the reading width not to wide, and follow this is more of the last block of logic.
Thus I would write your SQL for style:
select s.newf
,ROUND(ZEROIFNULL(pr) + ZEROIFNULL(pre)) AS monthlypremium
FROM (
SELECT q.form
,IFNULL(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pr
FROM target_quikplansurv AS q
LEFT JOIN target_newquikvalfsurdec AS n
ON q.plan = n.nplan
GROUP BY q.form, n.mvaldate
HAVING q.form='LN-5360'
) AS r
RIGHT JOIN (
SELECT q.forms
,ifnull(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pre
,iff(q.forms = 'L-5360', 'LN-5360', q.forms ) AS newf
FROM target_quikplan AS q
LEFT JOIN target_newquikvalf1 AS n
ON q.plan = n.nplan
GROUP BY q.forms, n.mvaldate
HAVING q.forms = 'L-5360'
) AS s
ON r.form = s.newf
Lastly what the SQL is doing
SELECT q.form
,IFNULL(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pr
FROM target_quikplansurv AS q
LEFT JOIN target_newquikvalfsurdec AS n
ON q.plan = n.nplan
GROUP BY q.form, n.mvaldate
HAVING q.form='LN-5360'
here you are grouping by the original source table mvaldate, but you are converting to a default ('2020-12-31') in the select, thus you are pointing out mvaldate can be null, but by group on the original the input
FORM, mvaldate, mannlzd
'LN-5360', '2020-11-30', 120
'LN-5360', '2020-12-31', 240
'LN-5360', null, 360
would give the output:
'LN-5360', '2020-11-30', 10
'LN-5360', '2020-12-31', 20
'LN-5360', '2020-12-31', 30
because the third row NULL is different to second row '2020-12-31'. Maybe you want that. But I suspect that would make people puzzled
But also by having the HAVING clause all the aggregation will occur. If you have 10 million rows with form being different to 'LN-3560' those values will all get calculated, and thrown away, which would imply you should swap to a WHERE clause, as you might be able to avoid data read (due to micro partitioning) and avoid the aggregation.
which makes me think you really want your SQL to look like:
SELECT s.newf
,ROUND(ZEROIFNULL(pr) + ZEROIFNULL(pre)) AS monthlypremium
FROM (
SELECT q.form
,IFNULL(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pr
FROM target_quikplansurv AS q
LEFT JOIN target_newquikvalfsurdec AS n
ON q.plan = n.nplan
WHERE q.form='LN-5360'
GROUP BY 1,2
) AS r
RIGHT JOIN (
SELECT q.forms
,ifnull(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pre
,iff(q.forms = 'L-5360', 'LN-5360', q.forms ) AS newf
FROM target_quikplan AS q
LEFT JOIN target_newquikvalf1 AS n
ON q.plan = n.nplan
WHERE q.forms = 'L-5360'
GROUP BY 1,2
) AS s
ON r.form = s.newf
But given your code as written it could also be:
SELECT s.newf
,ROUND(ZEROIFNULL(pr) + ZEROIFNULL(pre)) AS monthlypremium
FROM (
SELECT q.form
,IFNULL(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pr
FROM target_quikplansurv AS q
LEFT JOIN target_newquikvalfsurdec AS n
ON q.plan = n.nplan
WHERE q.form='LN-5360'
GROUP BY 1,2
) AS r
RIGHT JOIN (
SELECT q.forms
,IFNULL(n.mvaldate, '2020-12-31') AS reportdate
,SUM(n.mannlzd)/12 AS pre
,'LN-5360' AS newf
FROM target_quikplan AS q
LEFT JOIN target_newquikvalf1 AS n
ON q.plan = n.nplan
WHERE q.forms = 'L-5360'
GROUP BY 1,2
) AS s
ON r.form = s.newf

Related

GROUP BY total order quantity

we're trying to make our table add together all values in column 2 (QtyComp - an expression column of qtyorder * totalqty basically), where they have the same ItemNo (column 1).
So, we currently get the below:
ItemNo QtyComp
7441 3
7441 1
7441 5
What we want is it to see the SUM of the column QTYComp to give this result:
ItemNo QtyCom
7441 9
Our code is below; I've bolded the part that we need it to sum the results of:
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate,
workorderdetails.qtycomplete * ItemSpecFullStruc_2.totalqtyperroot
We would really appreciate some ideas!
Thanks,
Trish
If you want to sum these column, simply add a sum() syntax as follows:
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
sum(workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot) AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate
Also, you need to delete from group by that column.
For getting the desired result, set a GROUP BY only by ItemSpecs_2.itemno
assuming your current code gives you correct calculations, the lazy answer would be to write it as a CTE and then sum it, but this may result in sub optimal table scans - fine if it's just adhoc.
with mytemp as (
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate,
workorderdetails.qtycomplete * ItemSpecFullStruc_2.totalqtyperroot
)
select
itemno
,sum(QtyComp) as QtyComp
from mytemp
group by itemno

T-SQL query to show all the past steps, active and future steps

I have 3 tables in SQL Server:
map_table: (workflow map path)
stepId step_name
----------------
1 A
2 B
3 C
4 D
5 E
history_table:
stepId timestamp author
----------------------------
1 9:00am John
2 9:20am Mary
current_stageTable:
Id currentStageId waitingFor
------------------------------------
12345 3 Kat
I would like to write a query to show the map with the workflow status. Like this result here:
step name time author
----------------------------
1 A 9:00am John
2 B 9:20am Mary
3 C waiting Kat
4 D
5 E
I tried left join
select
m.stepId, m.step_name, h.timestamp, h.author
from
map_table m
left join
history_table h on m.stepId = h.stepId
I thought it will list all the records from the map table, since I am using left join, but somehow it only shows 3 records which is from history table..
So I changed to
select
m.stepId, m.step_name, h.timestamp, h.author
from
map_table m
left join
history_table h on m.stepId = h.stepId
union
select
m.stepId, m.step_name, '' as timestamp, '' as author
from
map_table m
where
m.stageId not in (select stageId from history_table)
order by
m.stepId
Then it list the result almost as I expected, but how do I add the 3rd table in to show the current active stage?
Thank you very much for all your help!! Much appreciated.
Looks like it's what you asked:
with map_table as (
select * from (values (1,'A')
,(2,'B')
,(3,'C')
,(4,'D')
,(5,'E')) t(stepId, step_name)
)
, history_table as (
select * from (values
(1,'9:00am','John')
,(2,'9:20am','Mary')) t(stepId, timestamp, author)
)
, current_stapeTable as (
select * from (values (2345, 3, 'Kat')) t(Id, currentStageId, waitingFor)
)
select
m.stepId, m.step_name
, time = coalesce(h.timestamp, case when c.waitingFor is not null then 'waiting' end)
, author = coalesce(h.author, c.waitingFor)
from
map_table m
left join history_table h on m.stepId = h.stepId
left join current_stapeTable c on m.stepId = c.currentStageId
I think a union fits well with the data and avoids the coalescing the values on multiple joins.
with timeline as (
select stepId, "timestamp" as ts, author from history_table
union all
select currentStageId, 'waiting', waitingFor from current_stageTable
)
select step_id, step_name, "timestamp", author
from
map_table as m left outer join timeline as t
on t.stepId = m.stepId

n Count the difference between values in two tables

I have Table PREV:
Client Ctg
1 CC
1 OVD
2 CC
3 OVD
and table ACT:
Client Ctg
1 OVD
2 CC
4 OVD
And i need to count the difference between those two tables for each product (how many clients left the product and how many are new ones)
So the result should be left CC -1 , OVD -1 new ones OVD 1
Those results can be in two different selects
I tried this :
select count (*) from PREV left join ACT on client = client where
cliet is null group by Ctg
but this is not working when one client has more products... :/
Please note that there are thousands of clients and each of them can have up to 5 products (Ctg)
Plus in each month (ACT and PREV are like February/January) are clients which left and clients which are new. In final form i want to count new ones as well.
If you want the number of records that are in the one table and not the other, do a left/right join between them and count the number of nulls. IE:
SELECT a.Ctg, a.Client PrevClient, b.Client ActClient
FROM PREV a
LEFT JOIN ACT b ON a.Client = b.Client AND a.Ctg = b.Ctg
So now ActClient will be null where it there is a record in the PREV table that is NOT in the ACT table. You can then simply get the count by wrapping that SQL in another SQL statement. IE
SELECT Ctg, COUNT(*) FROM (
SELECT a.Ctg, a.Client PrevClient, b.Client ActClient
FROM PREV a
LEFT JOIN ACT b ON a.Client = b.Client AND a.Ctg = b.Ctg
) Tmp
WHERE ActClient IS NULL
GROUP BY Ctg
So to get the count of the record in ACT that are not in PREV, you can simply use the same query with a RIGHT join. and change the a.Ctg to b.Ctg
you tried something like this?
select a.ctg,a.sum2-b.sum1 from
(select ctg, count(*) sum2 from prev group by ctg)a,
(select act.ctg ctg, count(*) sum1 from prev join act
on prev.client=act.client and prev.ctg=act.ctg group by act.ctg)b;
cte is doing calculation for PREV counts and then comparing with current counts.
; with cte
as
( select prev.Ctg, COUNT(ctg) as prevCount
from PREV
group by prev.Ctg
)
SELECT ACT.Ctg , COUNT(act.ctg) - cte.prevCount as Difference, COUNT(act.ctg) as CurrentCount, cte.prevCount as PrevCount
from ACT
join cte
on act.Ctg = cte.Ctg
group by ACT.Ctg, cte.prevCount
basic version:
SELECT COUNT(*) FROM [ACT] as a
where not exists (select * from [PREV] as p
where a.Client = p.Client and a.Ctg = p.Ctg)
ok, so thet try this one:
select a.Ctg, COUNT(a.Client) as ClientCoutThatAddThatCategory
from ACT as a
left outer join PREV as p
on a.Client=p.Client and a.Ctg=p.Ctg
where p.Client is NULL
group by a.Ctg
select p.Ctg, COUNT(p.Client) as ClientCoutThatLeftThatCategory
from ACT as a
right outer join PREV as p
on a.Client=p.Client and a.Ctg=p.Ctg
where a.Client is NULL
group by p.Ctg

Joining two queries horizontally

I wrote two queries below that produce one row of data each.
What is the best way to combine them such that I am LEFT with only a single row of data?
These are coming FROM two DISTINCT databases named : [ASN01] and [dsi_ASN_dsicx]
I have 70 pairs of databases like this but am showing only one for simplicity.
The fact that the three letter acronym ASN is common to both database names is no mistake and if needed can be a part of the solution.
Current Results:
Site, Elligence (header)
ASN, 100.00
Site, GP_Total (header)
ASN, 120.00
Desired results:
Site, GP_Total, Elligence (header)
ASN, 120.00, 100.00
SELECT 'ASN' AS Site ,
CASE SUM(perdblnc)
WHEN NULL THEN 0
ELSE -1 * SUM(PERDBLNC)
END AS GP_Total
FROM [ASN01].[dbo].[GL10110] T1
LEFT OUTER JOIN [ASN01].[dbo].[GL00105] T2 ON [T1].[ACTINDX] = [T2].[ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID IN ( '2' )
AND ACTNUMST IN ( '4200-0000-C', '6940-0000-C', '6945-0000-C',
'6950-0000-C' )
SELECT 'ASN' AS [Site] ,
SUM(pi.amount) AS [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi ON c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p ON pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt ON p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod NOT IN ( '5', '7' )
AND pt.paymentmethod IS NOT NULL
AND p.sdate >= '20120201'
AND p.sdate <= '20120229'
WIthout going through and changing any of your queries, the easiest way would be to use temp tables using the "WITH" common_table_expression. Table1 and Table2 are temp tables created from your select statements. Therefore, we select table1 and join table2.
Let me know if there are any syntax problems, I don't have anything to test this on presently.
;With Table1 as (SELECT 'ASN' as Site, Case sum(perdblnc)
WHEN NULL THEN 0
ELSE -1*sum(PERDBLNC) END as GP_Total
FROM [ASN01].[dbo].[GL10110] T1
Left Outer Join [ASN01].[dbo].[GL00105] T2
ON [T1]. [ACTINDX]= [T2]. [ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID in ('2')
AND ACTNUMST in ('4200-0000-C', '6940-0000-C', '6945-0000-C', '6950-0000-C'))
, Table2 as (SELECT
'ASN' as [Site],
SUM(pi.amount) as [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi on c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p on pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt on p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod not in ('5','7')
AND pt.paymentmethod is not null
AND p.sdate >='20120201' and p.sdate <= '20120229')
SELECT * FROM Table1
LEFT JOIN Table2 ON Table1.site = Table2.site
Hope this helps! Marks as answer if it is =)

TSQL - Return recent date

Having issues getting a dataset to return with one date per client in the query.
Requirements:
Must have the recent date of transaction per client list for user
Will need have the capability to run through EXEC
Current Query:
SELECT
c.client_uno
, c.client_code
, c.client_name
, c.open_date
into #AttyClnt
from hbm_client c
join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
select
ba.payr_client_uno as client_uno
, max(ba.tran_date) as tran_date
from blt_bill_amt ba
left outer join #AttyClnt ac on ba.payr_client_uno = ac.client_uno
where ba.tran_type IN ('RA', 'CR')
group by ba.payr_client_uno
Currently, this query will produce at least 1 row per client with a date, the problem is that there are some clients that will have between 2 and 10 dates associated with them bloating the return table to about 30,000 row instead of an idealistic 246 rows or less.
When i try doing max(tran_uno) to get the most recent transaction number, i get the same result, some have 1 value and others have multiple values.
The bigger picture has 4 other queries being performed doing other parts, i have only included the parts that pertain to the question.
Edit (2011-10-14 # 1:45PM):
select
ba.payr_client_uno as client_uno
, max(ba.row_uno) as row_uno
into #Bills
from blt_bill_amt ba
inner join hbm_matter m on ba.matter_uno = m.matter_uno
inner join hbm_client c on m.client_uno = c.client_uno
inner join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
and ba.tran_type in ('CR', 'RA')
group by ba.payr_client_uno
order by ba.payr_client_uno
--Obtain list of Transaction Date and Amount for the Transaction
select
b.client_uno
, ba.tran_date
, ba.tc_total_amt
from blt_bill_amt ba
inner join #Bills b on ba.row_uno = b.row_uno
Not quite sure what was going on but seems the Temp Tables were not acting right at all. Ideally i would have 246 rows of data, but with the previous query syntax it would produce from 400-5000 rows of data, obviously duplications on data.
I think you can use ranking to achieve what you want:
WITH ranked AS (
SELECT
client_uno = ba.payr_client_uno,
ba.tran_date,
be.tc_total_amt,
rnk = ROW_NUMBER() OVER (
PARTITION BY ba.payr_client_uno
ORDER BY ba.tran_uno DESC
)
FROM blt_bill_amt ba
INNER JOIN hbm_matter m ON ba.matter_uno = m.matter_uno
INNER JOIN hbm_client c ON m.client_uno = c.client_uno
INNER JOIN hbm_persnl p ON c.resp_empl_uno = p.empl_uno
WHERE p.login = #login
AND c.status_code = 'C'
AND ba.tran_type IN ('CR', 'RA')
)
SELECT
client_uno,
tran_date,
tc_total_amt
FROM ranked
WHERE rnk = 1
ORDER BY client_uno
Useful reading:
Ranking Functions (Transact-SQL)
ROW_NUMBER (Transact-SQL)
WITH common_table_expression (Transact-SQL)
Using Common Table Expressions

Resources