inner join results of "with" clause - sql

I have 2 with clauses like this:
WITH T
AS (SELECT tfsp.SubmissionID,
tfsp.Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND tfspm.PaymentOn >= '2013-05-01 12:00:00.000' AND tfspm.PaymentOn <= '2013-05-07 12:00:00.000')
SELECT SUM(Amount) AS TotalAmount,
campaignID,
Name
FROM T
GROUP BY campaignID,
Name;
and also:
WITH T1
AS (SELECT tfsp.SubmissionID,
tfsp.Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND tfspm.PaymentOn >= '2013-05-08 12:00:00.000' AND tfspm.PaymentOn <= '2013-05-14 12:00:00.000')
SELECT SUM(Amount) AS TotalAmount,
campaignID,
Name
FROM T1
GROUP BY campaignID,
Name;
Now I want to join the results of the both of the outputs. How can I do it?
Edited: Added the <= cluase also.
Reults from my first T:
Amount-----ID----Name
1000----- 2-----Annual Fund
83--------1-----Athletics Fund
300-------3-------Library Fund
Results from my T2
850-----2-------Annual Fund
370-----4-------Other
The output i require:
1800-----2------Annual Fund
83-------1------Athletics Fund
300------3-------Library Fund
370------4-----Other

You don't need a join. You can use
SELECT SUM(tfspm.PaymentOn) AS Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND ( tfspm.PaymentOn BETWEEN '2013-05-01 12:00:00.000'
AND '2013-05-07 12:00:00.000'
OR tfspm.PaymentOn BETWEEN '2013-05-08 12:00:00.000'
AND '2013-05-14 12:00:00.000' )
GROUP BY tfsp.campaignID,
cc.Name

If I am right, after a WITH-clause you have to immediatly select the results of that afterwards. So IMHO your best try to achieve joining the both would be to save each of them into a temporary table and then join the contents of those two together.
UPDATE: after re-reading your question I realized that you probably don't want a (SQL-) join but just your 2 results packed together in one, so you could easily achieve that with what I descibed above, just select the contents of both temporary tables and put a UNION inbetween them.

I was thinking it wrongly. Thanks for the help. This is how i achieved what exactly i want:
WITH
T AS (
SELECT tfsp.SubmissionID , Amount1 =
CASE
WHEN tfspm.PaymentOn >= '2013-01-10 11:34:54.000' AND tfspm.PaymentOn <= '2013-04-10 11:34:54.000' THEN tfsp.Amount
END
, Amount2 =
CASE
WHEN tfspm.PaymentOn >= '2013-05-01 11:34:54.000' AND tfspm.PaymentOn <= '2013-05-23 11:34:54.000' THEN tfsp.Amount
END
, tfsp.campaignID , cc.Name FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
)
SELECT ISNULL(SUM(Amount1),0) AS TotalAmount1, ISNULL(SUM(Amount2),0) AS TotalAmount2, campaignID , Name FROM T GROUP BY campaignID, Name;

Related

Join results of multiple select statements in sql

I have four select statements and I want to join them all to only get the common rows.
In an example, I'm providing 2 select statements:
SELECT
h.userid, 'Activity' as table_name,
h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[activity_history] h
INNER JOIN
(SELECT userid, MAX(stamp) as LatestDate
FROM [Animal].[SYSADM].[activity_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
SELECT
h.userid, 'Person' as table_name, h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[person_history] h
INNER JOIN
(SELECT userid, max(stamp) as LatestDate
FROM [Animal].[SYSADM].[person_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
I have tried INTERSECT, but it's not returning any rows, I want to see the common rows from both the select statements (actually I have 4 so I believe what works for 2 will work for 4)
Thanks in advance.
Update:
I tried inner join on 2 select statements and it gave me the desired result but now the question is how I can use inner join on 4 select statements.
SELECT DISTINCT t1.userid as A_UserID, t2.userid as P_UserID, t1.stamp as A_stamp, t2.stamp as P_stamp, datediff(dd,t1.stamp,GetDate()) as A_days_since, datediff(dd,t2.stamp,GetDate()) as P_days_since, t1.group_name, t1.table_name, t2.table_name
from
(SELECT h.userid, 'Activity' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[activity_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[activity_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t1
inner join
(SELECT h.userid, 'Person' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[person_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[person_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t2
on
t1.userid = t2.userid
order by T1.userid
Query Result
Forget about the UNION for a moment. Imagine you take that result and insert into Table1
Then depend what you mean the "common rows". If you want exact value but in different tables
SELECT userid, h.stamp, days_since, m.group_name
FROM Table1
GROUP BY userid, h.stamp, days_since, m.group_name
HAVING COUNT( table_name ) = 2 -- in this case 2 because are two types
-- Activity and Persons
After viewing your query result you also need to add DISTINCT to each of the queries on the UNION.

How to make a cell blank in a row from a query result?

I have a query as below:
SELECT
cc.chain_desc as chain_desc
,cc.chain_id as chain_id
,COUNT(distinct t.trans_id) as TranCount
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
GROUP BY cc.chain_desc, cc.chain_id
UNION
SELECT
'TOTAL'
,0
,COUNT(distinct t.trans_id)
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
The above query when executed reurns the below result:
I need the result to be displayed as below:
The column "Chain_Id" is of "integer" type, how can I make that blank?.
you can simply select null
.....
UNION
SELECT
'TOTAL'
, NULL::INTEGER
,COUNT(distinct t.trans_id)
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
because null is not a type you could try add above the first query
DEFINE test INT;
LET test = NULL;
......
SELECT
'TOTAL'
, test
,COUNT(distinct t.trans_id)
.....
Or like suggusted by #Jonathan Leffler use NULL::INTEGER or CAST(NULL AS INTEGER)
In Informix you can use NULL in the projection list, but the column must have a type. Since in Informix NULL does not have a type, you need to use a CAST.
SELECT NULL::INTEGER AS id FROM systables WHERE tabid = 1;
SELECT CAST(NULL AS INTEGER) AS id FROM systables WHERE tabid = 1;
You can check the answers to this other question (Informix: Select null problem).
You can check the IBM Knowledge Center (NULL Keyword).
One way is to convert to NULL:
(case when cc.chain_id <> 0 then cc.chain_id end) as chain_id
Another is to convert everything to a string:
(case when cc.chain_id <> 0 then cast(cc.chain_id as varchar(255)) else '' end) as chain_id

Write query using JOINS

select
store, sum(value)
from
rms.sa_tran_head
where
store_day_seq_no in (select store_day_seq_no
from rms.sa_store_day
where store in (3003)
and business_date = '01-JAN-2015')
and tran_type in ('SALE', 'RETURN')
group by
store;
How to write the above query using JOINS..
SELECT
sd.store,
SUM(TH.VALUE) AS GROSS ,
SUM(ti.qty) AS QTY
FROM rms.sa_tran_head AS th
JOIN rms.sa_store_day AS sd
ON th.store_day_seq_no = sd.store_day_seq_no
JOIN rms.sa_tran_item AS ti
ON ti.tran_seq_no = th.tran_seq_no
WHERE sd.store in (3003) --in (3003) use in if more than 1 value
AND sd.business_date = '01-JAN-2015'
AND th.tran_type IN ('SALE','RETURN')
GROUP BY
sd.store;
When I add other columns of another table it is showing different values...
I assumed store_day_seq_no is FK for the table rms.sa_store_day and the query with JOIN like this,
SELECT
sd.store,
SUM(sd.value) AS [Sum]
FROM rms.sa_tran_head AS th
JOIN rms.sa_store_day AS sd
ON th.store_day_seq_no = sd.store_day_seq_no
WHERE
sd.store = 3003 --in (3003) use in if more than 1 value
AND sd.business_date = '01-JAN-2015'
AND th.tran_type IN ('SALE','RETURN')
GROUP BY
sd.store;
I think this is ok.
SELECT
t1.store,
SUM(t1.Value) AS Sum_Value
FROM rms.sa_tran_head t1
INNER JOIN sa_store_day t2 ON t1.store_day_seq_no = t2.store_day_seq_no
WHERE t2.store IN ( 3003 )
AND t2.business_date = '01-JAN-2015'
AND t1.tran_type IN ( 'SALE' , 'RETURN' )
GROUP BY t1.store

sql distinct select from multiple select

What is the best way to join the following three select and to get non duplicated contact.id ?
Any idea ?
SELECT distinct ct.id
FROM [Customer].[dbo].[Contact] ct
left join [Customer].[dbo].[HN_Customer_ids] hnids
on ct.id = hnids.contact_id
left join [CustomerTransactions].[dbo].[Transaction_Header] trh
on trh.Customer_ID = hnids.HN_customer_id
where trh.actual_transaction_date > '20120218'
Result: 231360
SELECT count(distinct(contact_id))
FROM [Customer].[dbo].[Restaurant_Attendance]
where ( created > '2012-02-18 00:00:00.000' or modified > '2012-02-18 00:00:00.000')
AND
Result: 167128
SELECT distinct aaa.id
FROM [Customer].[dbo].[Contact] aaa
left join [Customer].[dbo].[Wifinity_Devices] bbb
on aaa.wifinity_uniqueID = bbb.[CustomerUniqueID]
and startconnection > '2012-02-17'
Result: 77290
Use union. So:
SELECT ct.id
FROM [Customer].[dbo].[Contact] ct join
[Customer].[dbo].[HN_Customer_ids] hnids
on ct.id = hnids.contact_id join
[CustomerTransactions].[dbo].[Transaction_Header] trh
on trh.Customer_ID = hnids.HN_customer_id
WHERE trh.actual_transaction_date > '20120218'
UNION
SELECT contact_id
FROM [Customer].[dbo].[Restaurant_Attendance]
WHERE (created > '2012-02-18 00:00:00.000' or
modified > '2012-02-18 00:00:00.000')
UNION
SELECT aaa.id
FROM [Customer].[dbo].[Contact] aaa ;
The left joins are unnecessary in the first and third queries. In the first, the where undoes the left join anyway. In the third, you are choosing an id from the first table, and the left join does no filtering.
use union
SELECT ct.id
FROM [Customer].[dbo].[Contact] ct
left join [Customer].[dbo].[HN_Customer_ids] hnids on ct.id = hnids.contact_id
left join [CustomerTransactions].[dbo].[Transaction_Header] trh on trh.Customer_ID = hnids.HN_customer_id
where trh.actual_transaction_date > '20120218'
union
SELECT contact_id
FROM [Customer].[dbo].[Restaurant_Attendance]
where ( created > '2012-02-18 00:00:00.000' or modified > '2012-02-18 00:00:00.000')
union
SELECT aaa.id
FROM [Customer].[dbo].[Contact] aaa left join [Customer].[dbo].[Wifinity_Devices] bbb on aaa.wifinity_uniqueID = bbb.[CustomerUniqueID]
and startconnection > '2012-02-17'
Assuming all queries run against the same Contact table, your use of left outer join is effectively causing the third query to return all the contacts. Unless the second query can add contact_ids not found in the Contact table, the end result is equivalent to:
select /* distinct, if not a pk */ contact_id from Customer.dbo.Contact
Your row counts suggest that maybe these are actually tables from different databases. Is that the case?

SQL Select Statement SubSelect not working correct

I have 2 SQL Select Queries which I need in two seperare columns. The code I have just now does exactly that, but it also gives 2 nulls. Here is my code :
Select a.Budget, b.Actual_Income FROM
(Select sum(subscriptions.Bill_Amount) as Budget
From imis.dbo.Name Name INNER JOIN imis.dbo.Subscriptions Subscriptions ON Name.ID=Subscriptions.ID
Where Member_Type = 'MM' and Name.Status = 'a' and Product_Code = 'Annual' and Subscriptions.Status = 'a') AS a
FULL JOIN
(SELECT sum(Amount * -1) as Actual_Income
FROM imis.dbo.Name Name INNER JOIN imis.dbo.Trans Trans ON Name.ID=Trans.BT_ID
WHERE PRODUCT_CODE ='ANNUAL' and Transaction_Date >= '21/10/2013' and Batch_Num <> 'DD131031-3') AS b
ON a.Budget = b.Actual_Income
This Is what It returns
Budget Actual_Income
6367005.00 NULL
NULL 665712.37
Any help is much appreciated!
You have a FULL JOIN. Change it to INNER JOIN.
Check this link for better understanding SQL JOINS
If your results were meant to be as the following:
Budget Actual_Income
6367005.00 665712.37
Then you can do subselect or aggregate:
SubSelect:
Select (Select sum(subscriptions.Bill_Amount) as Budget
From imis.dbo.Name Name INNER JOIN imis.dbo.Subscriptions Subscriptions ON Name.ID=Subscriptions.ID
Where Member_Type = 'MM' and Name.Status = 'a' and Product_Code = 'Annual' and Subscriptions.Status = 'a') Budget,
(SELECT sum(Amount * -1) as Actual_Income
FROM imis.dbo.Name Name INNER JOIN imis.dbo.Trans Trans ON Name.ID=Trans.BT_ID
WHERE PRODUCT_CODE ='ANNUAL' and Transaction_Date >= '21/10/2013' and Batch_Num <> 'DD131031-3') as Actual_Income
aggregate:
Select MAX(a.Budget), MAX(b.Actual_Income) FROM
(Select sum(subscriptions.Bill_Amount) as Budget
From imis.dbo.Name Name INNER JOIN imis.dbo.Subscriptions Subscriptions ON Name.ID=Subscriptions.ID
Where Member_Type = 'MM' and Name.Status = 'a' and Product_Code = 'Annual' and Subscriptions.Status = 'a') AS a
FULL JOIN
(SELECT sum(Amount * -1) as Actual_Income
FROM imis.dbo.Name Name INNER JOIN imis.dbo.Trans Trans ON Name.ID=Trans.BT_ID
WHERE PRODUCT_CODE ='ANNUAL' and Transaction_Date >= '21/10/2013' and Batch_Num <> 'DD131031-3') AS b